为什么此查询会针对不同的日期格式返回不同的结果?

时间:2013-01-22 07:35:05

标签: sql sql-server date casting

我有一个名为book_data的表,其中batch_dt作为sql server中varchar类型的列名。

当我通过查询时

SELECT DISTINCT batch FROM book_data 

它给了我以下结果

  batch_dt
-------------
 2012-10-31
-------------
 2012-11-01
-------------
 2012-11-02
-------------
 2012-11-03
-------------
      .
      .
      .

现在我正在做的是获取两个日期之间的记录总数。相当简单的查询。

SELECT COUNT(*) FROM book_data WHERE CONVERT(varchar(12),CONVERT(datetime,batch_dt),101) BETWEEN '11/02/2012' and '10/31/2012'

结果是 的 112

只需将月份从 02 更改为 2 ,查询就会给我 218 结果

SELECT COUNT(*) FROM book_data WHERE CONVERT(varchar(12),CONVERT(datetime,batch_dt),101) BETWEEN '11/2/2012' and '10/31/2012'
为什么这种不同的行为?

4 个答案:

答案 0 :(得分:3)

改为使用CAST(batch_dt AS DATE),并以YYYYMMDD格式以语言中立的方式传递日期。通过这种方式,它将被归为日期,而不是varchar

SELECT COUNT(*) 
FROM book_data 
WHERE CAST(batch_dt AS DATE)
BETWEEN '20121102' and '20121130'

但是,这不安全,如果barch_dt中的任何值格式错误,您将收到转换错误。在这种情况下,您可以添加ISDATE(batch_dt) = 1以确保它是有效的数据时间。但最好将此列数据类型DateTime

需要注意的另一件事:是SQL Server中BETWEEN 非对称,这意味着BETWEEN '11/02/2012' and '10/31/2012'被评估为:

DATE >= '11/02/2012' 
AND
DATE <= '10/31/2012'

永远不会成立,它适合你的原因是日期被比作字符串而不是日期。但你必须保持BETWEEN the small value and the biggest value

答案 1 :(得分:2)

SELECT COUNT(*) 
FROM book_data 
WHERE CONVERT(DATETIME,batch_dt,101) BETWEEN '11/2/2012' and '10/31/2012'

这会更合适

答案 2 :(得分:2)

您将字符串与BETWEEN进行比较。如果您这样做,您需要确保以正确的顺序进行比较=&gt; YYYYMMDD MM:SS是一个正确的订单。

如果可以,请添加类型为datetime的列,并在数据库中存储实际日期时间值。如果您不能这样做,您可以拆分值并自己构建日期值。这比使用CONVERT()CAST()慢得多,但您可以确保它甚至可以使用错误的日期字符串。

您可以使用PATINDEX(),LEFT(),RIGHT()关键字获取所需的值,或使用split()函数(您可以找到许多版本的Google,例如https://codereview.stackexchange.com/questions/15125/sql-server-split-function-optimized)。如果您使用拆分功能,则按/拆分,然后从位置获取年,月,日。

但最好还是将正确的日期时间值存储在数据库中。

答案 3 :(得分:1)

您会得到这种不同的行为,因为您不比较日期而是比较字符串/ varchars。

对于Date(或DateTime),10/2/201210/02/2012相同。

但是对于string,这些值(当然)是不同的。就像您将'abcd''ab0cd'

进行比较一样