SQL server 2005 - 查询日期范围内的任意时间间隔

时间:2011-03-29 18:31:33

标签: sql-server sql-server-2005 tsql

我有一个DateTime列。我想在一定日期范围内从8:30到16:15提取所有记录。我的问题是我需要将小时和分钟作为单个时间值进行比较。我可以测试DATEPART大于或小于几个小时的值,但如果我这样做了几分钟,如果当天晚些时间的分钟值较小,我的查询将失败。

我已经查看了INTERVAL,BETWEEN,DATEPART,DATEDIFF等,但是如果没有“TimeOfDay”值可以在不同日期的记录中使用,那么就看不到如何做到这一点。

我已经尝试减去日期的年,月和日部分,这样我就可以只比较一天中的时间,但是当试图减去日期部分时,我会得到一个过度错误:

这部分有效:

select - cast( DATEPART(YEAR, CallTime) as integer) from history

这失败了:

select DATEADD(YEAR, - cast( DATEPART(YEAR, CallTime) as integer), CallTime) 
from history where calltime is not null

我还尝试将小时和分钟部分投射到字符,连接它们并与我的目标范围进行比较,但这也失败了。

我相信较新版本的SQL服务器可能具有处理这种情况的功能,但我无法使用。

我希望并想象有一个简单明了的解决方案,但它让我望而却步。

3 个答案:

答案 0 :(得分:2)

尝试创建一个“MinuteOfDay”函数,该函数根据日期时间计算当天经过的分钟数。

CREATE FUNCTION dbo.[MinuteOfDay] 
(
    @dt datetime
)
RETURNS int
AS
BEGIN
    RETURN (datepart(hh,@dt)*60) + datepart(mi,@dt) 
END

然后使用该函数的结果进行过滤。

select * 
from MyTable t 
where dbo.MinuteOfDay(t.SomeDateTimeColumn) between dbo.MinuteOfDay('1900-1-1 08:30:00') and dbo.MinuteOfDay('1900-1-1 16:15:00')

答案 1 :(得分:0)

试一试:

DECLARE @StartDateTime  datetime
       ,@EndDateTime    datetime

--date range is ALL of January 1st up to & including 31st
SELECT @StartDateTime='2011/01/01'
      ,@EndDateTime='2011/01/31'

SELECT
    *
    FROM TableName  t
    WHERE 
        t.ColumnDate>=@StartDateTime AND t.ColumnDate<@EndDateTime+1 --date range
        AND LEFT(RIGHT(CONVERT(char(19),t.ColumnDate(),120),8),5)>='08:30' --time range start
        AND LEFT(RIGHT(CONVERT(char(19),t.ColumnDate(),120),8),5)<='16:15' --time range end

如果你有关于t.ColumnDate的索引,这应该可以利用它。

WHERE的“日期范围”部分会丢弃不在预期日期范围内的行。 WHERE的“时间范围开始”部分抛弃了早期的行,“时间范围结束”抛弃了迟到的行。

答案 2 :(得分:0)

DATETIME值可以转换为FLOAT。实际上,DATETIME存储为FLOAT。

FLOAT的整个部分是自'12 / 31/1899'以来的日子(或接近)。小数部分是小时数除以24.所以0.5 = 12中午。

08:30是0.3541666667

16:15是0.6770833333

选择CAST(CAST('2011-03-25 08:30:00'作为DATETIME)作为FLOAT)= 40625.3541666667

选择CAST(CAST('2011-03-25 16:15:00'AS DATETIME)as FLOAT)= 40625.6770833333

所以你可以写

SELECT * FROM users WHERE hire_date&lt; 40625.3541666667

使用DATETIME作为FLOAT,您可以使用最适合您查询的数学函数。