2012-03-01 80 views
0

我的影片让我结果的列表为2012年2月得到的where子句的一个月LINQ 2 SQL查询不正确的日期比较结果在SQL Server 2008 R2

DECLARE @p0 DateTime = '2012-02-01 00:00:00.000' 
DECLARE @p1 DateTime = '2012-02-29 23:59:59.999' 
.... 
WHERE (CONVERT(DATE, [t0].[DatePlaced]) >= @p0) AND (CONVERT(DATE, [t0].[DatePlaced]) <= @p1) 

在运行此我”获得2012年3月1日的结果以及2012年2月的所有结果。

如果我将where子句更改为使用BETWEEN,那么结果仅包含2月份的日期。

WHERE [t0].[DatePlaced] BETWEEN @p0 AND @p1 

我正在使用.net 4和SQL Server 2008 R2(带和不带SP1)。

将日期切换到2011年3月1日,我的查询结束日期为'2011-02-28 23:59:59.999'的结果相同。

除了使用LINQ 2 SQL不支持的BETWEEN之外,是否还有另一种获得仅用于2/2012的结果的方法?

回答

4

.999向上舍入到第二天的午夜。你可以检查:

DECLARE @p1 DateTime = '2012-02-29 23:59:59.999'; 
SELECT @p1; 

你会得到什么?

,而不是试图找出今天的最后时刻(取决于数据类型和精度,这将是不同的),你想,而不是什么是开放式的日期范围:

DECLARE @p0 DATE = '2012-02-01', 
     @p1 DATE = '2012-03-01'; 
.... 
WHERE [t0].[DatePlaced] >= @p0 
AND [t0].[DatePlaced] < @p1 

甚至更​​容易是只传递的开始日期和说:

DECLARE @p0 DATE = '2012-02-01'; 

.... 
WHERE [t0].DatePlaced >= @p0 
AND [t0].DatePlaced < DATEADD(MONTH, 1, @p0) 

有关日期时间精心制作的一些想法最佳实践:

http://sqlblog.com/blogs/aaron_bertrand/archive/2009/10/16/bad-habits-to-kick-mishandling-date-range-queries.aspx

有关为什么BETWEEN(通过扩展>= AND <=)是邪恶的一些信息:

http://sqlblog.com/blogs/aaron_bertrand/archive/2011/10/19/what-do-between-and-the-devil-have-in-common.aspx

而且蒂博尔出​​色的日期/时间资源:

http://www.karaszi.com/SQLServer/info_datetime.asp

3

如果您需要按月往往选择,你可以考虑将两个计算列的表 - 一个是一个月,一个年度:

ALTER TABLE dbo.YourTable 
ADD DatePlacedYear AS YEAR(DatePlaced) PERSISTED 

ALTER TABLE dbo.YourTable 
ADD DatePlacedMonth AS MONTH(DatePlaced) PERSISTED 

这两个新列由SQL自动计算服务器,它们是持久的(例如表的存储的一部分),甚至可以在它们上面放置索引,如果这对你有意义的话。

与那些在地方,你现在可以使用这样的查询:

SELECT (columns) 
FROM dbo.YourTable 
WHERE DatePlacedYear = 2012 AND DatePlacedMonth = 2 

从2012年2月获得的所有数据

这是一个经典的空间VS-速度的权衡 - 通过存储每行需要两个额外的列,你需要更多的空间 - 但作为回应,查询变得更容易,如果你有一个索引(DatePlacedYear, DatePlacedMonth),你的查询应该(相当快)。

+0

而不是添加计算列,我只是简单地比较日期的月份和年份部分。我相信这是一种性能上的折衷,但它只是用于内部报告,所以目前这不是什么大问题。 – 2012-03-11 04:47:24

0

而不是使用AddMilliseconds(-1)试使用AddMilliseconds(-3)

请参阅this question SQL Server如何处理毫秒

+2

依靠毫秒是有问题的。如果底层数据类型转换为SMALLDATETIME会怎么样?现在你的结果又回来了。如果它转换为DATETIME2(> 2)会怎样?现在,你的范围的结束实际上是在一天结束之前,你理论上可能会错过数据。一个开放式的日期范围实际上是获得一整天数据的唯一面向未来的方法。 – 2012-03-02 00:14:33