2011-03-31 44 views
0

我想做一个网站,从数据库中获取一些数据并用这些数据生成一些统计数据。什么是最好的方法来获得一个整月的日期?

这个想法是允许用户选择一个月,然后只查询该月份的数据。因此,如果用户选择1月,请查询数据> 01/01/2011和< 31/01/2011。

我想过从月份开始生成数据,然后加上一个月并减去一天,这样我就得到了给定月份的最后一天,但我不认为这是最好的方法,也不知道如何从给定月份生成完整日期。

任何想法?

+0

你为什么认为这不是最好的方法?非常简单的日期操作有什么问题? – 2011-03-31 06:50:38

+0

@Stofke SQL的设计是什么?用于日期计算?他问的是如何得到日期,而不是如何比较。 – 2011-03-31 07:20:21

+0

@Stofke他问的不是如何查询,而是如何获得一个范围。 – 2011-03-31 07:34:15

回答

4

SQL中心的方式:

SELECT * FROM `foo` WHERE MONTH(`date`) = 3 AND YEAR(`date`) = 2011 

替换从您的选择年份和月份的数字。

PHP中心的方式:

$month = 3; 
$year  = 2011; 
$firstDay = "$year-$month-1"; 
$lastDay = "$year-$month-" . date('t', strtotime($firstDay)); 

$query = "SELECT * FROM `foo` 
      WHERE `date` >= '$firstDay' 
      AND `date` <= '$lastDay'"; 
+0

是的,该SQL甚至比我的解决方案更好 – Stofke 2011-03-31 06:48:05

+0

不错,太棒了!我不知道MySQL中的这句话我已经尝试过,并且效果很好:) – 2011-03-31 06:55:55

+0

MySQL可以在MONTH和YEAR搜索时使用索引吗?还是会诉诸表扫描? – cHao 2011-04-02 15:20:23

0

如果要保存您的数据DateTimeStamp,只需添加条件查询,因为这只会从特定的一年中特定月份返回结果。你可以使用这个LIKE子句。上个月

1

选择记录:

select `id` 
from `orders` 
where `created_at` > LAST_DAY(DATE_SUB(CURDATE(), INTERVAL 1 MONTH)) 
    AND `created_at` < DATE_ADD(LAST_DAY(CURDATE()), INTERVAL 1 DAY) 

与前一个月:

select `id` 
from `orders` 
where `created_at` > LAST_DAY(DATE_SUB(CURDATE(), INTERVAL 2 MONTH)) 
    AND `created_at` < DATE_ADD(LAST_DAY(CURDATE() - INTERVAL 1 MONTH), INTERVAL 1 DAY) 

+0

这正是我试图避免:) – 2011-03-31 07:08:34

+0

@安东尼完全相反,这就是你实际上正在寻找。你可以使用'CURDATE()'代替'2010-03-01'格式的任何日期代表所需的月份,其余的将由mysql计算,而select tiself将以最有效的方式完成。 – 2011-03-31 08:47:22

1

这里是给你一个教训。

大多数新手程序员都在寻找“最好”,“最有效”的方法和东西。
虽然他们通过代码量来判断效率...... “代码少 - 效率更高!” - 他们认为。当然是错的。让我们比较一下你的“高效”解决方案与“低效”之一:

mysql> explain select * from Board where year(date) = 2011 and month(date) = 1; 
+----+-------------+-------+------+---------------+------+---------+------+-------+-------------+ 
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra  | 
+----+-------------+-------+------+---------------+------+---------+------+-------+-------------+ 
| 1 | SIMPLE  | Board | ALL | NULL   | NULL | NULL | NULL | 18113 | Using where | 
+----+-------------+-------+------+---------------+------+---------+------+-------+-------------+ 

mysql> explain select * from Board where date > '2010-12-31' and date < '2011-02-01'; 
+----+-------------+-------+-------+---------------+------+---------+------+------+-------------+ 
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra  | 
+----+-------------+-------+-------+---------------+------+---------+------+------+-------------+ 
| 1 | SIMPLE  | Board | range | date   | date | 9  | NULL | 325 | Using where | 
+----+-------------+-------+-------+---------------+------+---------+------+------+-------------+ 

通知possible keysrows参数。

在后一种情况下,数据库将获得您需要的确切行,在前者中 - 将选择表中的每一行,在日期中应用函数并将其与常量进行比较。

也是一样从这个可怜的家伙谁是你的无知的评论后删除了很好的回答了解决方案:

mysql> explain select * from Board where `date` > LAST_DAY(DATE_SUB('2011-01-15', INTERVAL 1 MONTH)) AND `date` < DATE_ADD(LAST_DAY('2011-01-15'), INTERVAL 1 DAY); 
+----+-------------+-------+-------+---------------+------+---------+------+------+-------------+ 
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra  | 
+----+-------------+-------+-------+---------------+------+---------+------+------+-------------+ 
| 1 | SIMPLE  | Board | range | date   | date | 9  | NULL | 325 | Using where | 
+----+-------------+-------+-------+---------------+------+---------+------+------+-------------+ 

纳夫说。

+0

经验教训很好,但不礼貌真的很糟糕。请下次更有礼貌。我是noob,在编程时非常喜欢,但我只是想学习。没有人知道,请记住这一点。 – 2011-04-01 12:16:48

+0

@Antonio在我的回答中,有什么不礼貌的东西让你感觉如此受到虐待? – 2011-04-01 12:19:35

+0

这可能与文化差异有关,如果你真的觉得你的评论并不礼貌,我不知道和抱歉。在西班牙,给某个人打电话Ignorant有点粗鲁,但我非常感谢你的评论,因为它对我很有帮助,下次我可以自己检查一下查询的性能。 – 2011-04-01 12:22:29

相关问题