2016-05-12 146 views
0

这是太阳日期,但其类型的列是varchar我想选择在(1395-02)区间内的所有行,但我只从2行中获得1行 这里是我试过的Mysql Date Solar Date

SELECT * FROM `products_records` 
    WHERE Date_FORMAT(`products_records`.`Inserted_Date`,'%Y-%m')='1395-02' 

注:某些日期像数据库1395年2月30日变更为0000-00-00,这就是为什么我用Varchare代替日期此列

回答

0

首先,请注意,您在使用DATE_FORMAT()超出其预定用途。 DATE_FORMAT()的第一个参数应该是一个日期时间值 - 不是字符串 - 但是MySQL对它的隐式转换非常慷慨,所以它允许你摆脱技术上对该功能的有效使用。实际上,你隐式地将字符串转换为日期,然后使用一个期望日期的函数......但某些日期是无效的,因此隐式转换可能会失败。运行您的查询后,SHOW WARNINGS;可能会揭示这一点。

实际上,您理论上应该使用STR_TO_DATE()将字符串转换为适当的日期时间,然后使用该结果作为DATE_FORMAT()的第一个参数。

但是,这仍然是一个错误的解决方案,因为它违反了基本规则,您不希望使用列作为WHERE子句中大多数函数的参数...因为当您这样做时,服务器必须评估表中每一行的表达式,并且您的索引不能用于优化查询。你失去了所谓的“sargability”,并且随着表的增长,查询变慢。这是一般RDBMS的局限性,而不仅仅是MySQL。

更好的是使用常数WHERE inserted_date >= '1395-02-01' AND inserted_date < '1395-03-01'。这样,如果索引可用,它可以显着提高您的性能。

因为你的日期是yyyy-mm-dd格式,所以它们的词汇顺序恰好也是按时间顺序排列的,所以即使上面的查询将在当前设置中使用字符串比较进行评估,答案仍然会是正确的,并且查询计划将是最佳的。如果日期实际上是以日期存储的,这仍然是首选形式 - 不使用WHERE中的函数。

但是,您也希望使用无效日期,您的服务器需要ALLOW_INVALID_DATES包含在@@SQL_MODE中。那么任何一个月都可以有31天。我不知道为什么这实际上是一个功能,但它在这里:

服务器要求月份和日期值是合法的,而不是分别在1到12和1到31范围内。禁用严格模式后,无效日期(如“2004-04-31”)将转换为“0000-00-00”,并生成警告。启用严格模式后,无效日期会生成错误。要允许这样的日期,使ALLOW_INVALID_DATES.

http://dev.mysql.com/doc/refman/5.7/en/sql-mode.html#sqlmode_allow_invalid_dates

虽然我从来没有一个理由使用无效的日期,它按理说,日期/时间函数会窒息在他们身上,但这项设定可能是为了让这些值按预期工作所需要的。

+0

谢谢,它最好的答案,为我工作 –