2010-01-04 102 views
8

如何仅比较SQL Server 2005中DateTime数据类型的时间部分?例如,我想在特定时间后获取MyDateField所在的所有记录。下面的例子是一个很长的,也许不是快速的方法。 我想所有的日期,其中MyDateField大于12:30:50.400比较SQL Server 2005中DateTime数据类型的时间部分

SELECT * 
FROM Table1 
WHERE  ((DATEPART(hour, MyDateField) = 12) AND (DATEPART(minute, MyDateField) = 30) AND (DATEPART(second, MyDateField) = 50) AND (DATEPART(millisecond, MyDateField) > 400)) 
     OR ((DATEPART(hour, MyDateField) = 12) AND (DATEPART(minute, MyDateField) = 30) AND (DATEPART(second, MyDateField) > 50)) 
     OR ((DATEPART(hour, MyDateField) = 12) AND (DATEPART(minute, MyDateField) > 30)) 
     OR ((DATEPART(hour, MyDateField) > 12)) 
+0

请注意,如果您确实需要分别处理日期和时间,则会有效地破坏规范化规则。日期时间值是日期的特定时间点。日期和时间是一个多值字段,应该被分解。你的代码运行缓慢的原因是你没有正确地标准化它。 – 2010-01-04 18:26:31

+0

@Lasse - 你会用多久?毫无疑问,您不会将日期存储在不同的字段中:日,月,年,小时,分钟,工作日,周末,季度,星期。 – JeffO 2010-01-04 18:46:23

+0

@Lasse - 当然,我可以在日期和时间字段中分隔DateTime字段。但是,然后我会有同样的问题来比较日期和时间在一起。 – 2010-01-04 19:04:45

回答

10
SELECT * 
FROM Table1 
WHERE DATEADD(day, -DATEDIFF(day, 0, MyDateField), MyDateField) > '12:30:50.400' 
+0

我认为这是迄今为止最好的解决方案。这很清楚,也很容易理解。它也是关于只有查询而不是数据库结构的最快解决方案。 – 2010-01-05 13:33:00

5

这个怎么样?

SELECT (fields) 
FROM dbo.YourTable 
WHERE DATEPART(HOUR, MyDate) >= 12 
    AND DATEPART(MINUTE, MyDate) >= 23 
    AND DATEPART(SECOND, MyDate) >= 45 

小时以24小时格式给出,例如, 12意味着中午12点,15意味着下午3点。

DATEPART对分,秒等也有“部分”。只要你喜欢,你当然可以在WHERE子句中使用尽可能多的日期部分。

+0

如果中午是截止时间,那么逻辑可能应该是'hour> = 12'或者可能是'hour> 12或(hour = 12 and millisecond> 0)'。 – LukeH 2010-01-04 17:27:19

+0

@Luke:好点,是的 - 我打算使用> = .... – 2010-01-04 17:30:05

+0

但我也想考虑时间部分的其他部分,不仅是小时。 – 2010-01-04 17:46:44

-1

转换(VARCHAR(10),指明MyDate,108)

这给你格式HH的时间字符串:MM:SS。

那么你可以做你想做的事情

+0

时间部分还包含毫秒...还有一个格式还返回全部时间部分?我正在寻找的是一种排除日期部分只留下时间的方法。 – 2010-01-04 17:50:38

1

我想做任何比较的提取日期时间数据类型的时间部分,并进行比较。我找到了一种在StackOverflow中提取日期部分的方法。如果只有我一个人的日期部分,它只是从源日期时间减去日期:

datePortion = DATEADD(日,DATEDIFF(日,0,sourceDate),0)
timePortion = DATEDIFF(毫秒, datePortion,sourceDate

所以以提取在SQL Server 2005中的时间部分的宏是:

F(X)= DATEDIFF(毫秒,DATEADD(天,DATEDIFF(日,0,sourceDate ),0),sourceDate

现在查询以比较日期时间字段的时间部分,用12:30:50.400是:

SELECT * 
FROM Table1 
WHERE 
     DATEDIFF(millisecond, DATEADD(day, DATEDIFF(day, 0, DateTimeField), 0), DateTimeField) 
     > 
     DATEDIFF(millisecond, DATEADD(day, DATEDIFF(day, 0, '1900-01-01T12:30:50.400'), 0), '1900-01-01T12:30:50.400') 

我已经测试该查询与其他类型的查询,包括使用减法运算符( ' - ')和CONVERT。执行计划比较表明,这是执行此操作最快的方法。我还测试了查询执行的实际时间......没有明显的最快方法。

+0

要整理查询,而不是提高性能,这是一个非常好的解决方案,如果你把它扔到UDF中。这样你可以把它写成WHERE dbo.GetTime(MyDateField)> = @ SomeTime'。 – Aaronaught 2010-01-04 21:25:31

+0

在开始时,我想知道是否可以获得更多的性能只改变查询。这是可能的,但不是那么多,不到2%。我无法找到GetTime函数。 – 2010-01-04 21:54:51

1

其他人张贴形成查询的替代方法,但我想的东西回应你的第一段说:

下面的例子是一个非常漫长和做的可能不是快方式这个。

表现方面,如果您有一个DATEPART或10 DATEPARTS在那里并不重要,事实上,你甚至有一个DATEPART是什么会损害表现。

如果您需要按时比较,但没有日期,那么Lasse的评论是正确的钱 - 你需要规范化为单独的日期/时间列。实际上,SQL 2008引入了datetime类型,并建议您使用它们而不是datetime。你在SQL 2005中没有这个,但是你可以用它来解决这个问题,比如说,一天中的一个ticks字段,以及一个强制日期列的所有dateparts为零的检查约束。

如果以后需要在完整日期+时间内执行过滤器,则很容易创建计算列,并且如果性能对于这些问题是个问题,则可以保留该列并在其上创建索引。

+0

你完全正确! =)我问了这个问题,因为我想知道如何解决它,它的方式,而不改变数据库。事实上,所有QUERY-ONLY解决方案都是相同的速度顺序,无论如何,所有速度都会变慢......我现在测试它......但使用DATEADD和DATEDIFF是最差的。 – 2010-01-04 20:45:51