【问题标题】:SQL server 2005 - query aribitrary time interval in date rangeSQL server 2005 - 查询日期范围内的任意时间间隔
【发布时间】:2011-03-30 04:56:15
【问题描述】:

我有一个 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 Server 可能具有处理这种情况的功能,但我无法使用。

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

【问题讨论】:

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


    【解决方案1】:

    尝试创建一个“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')
    

    【讨论】:

    • 谢谢你!这很好地解决了这个问题。在我进步的自行车道路上的半砖是我被困在尝试在查询本身中做所有事情,而不是创建一个函数。
    【解决方案2】:

    试一试:

    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 的“时间范围开始”部分丢弃时间较早的行,而“时间范围结束”部分丢弃时间较晚的行。

    【讨论】:

      【解决方案3】:

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

      FLOAT 的整个部分是自“1899 年 12 月 31 日”(或接近的日期)以来的天数。小数部分是小时数除以 24。所以 0.5 = 中午 12 点。

      08:30 是 0.3541666667

      16:15 是 0.6770833333

      SELECT CAST(CAST('2011-03-25 08:30:00' AS DATETIME) AS FLOAT) = 40625.3541666667

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

      所以你可以写

      SELECT * FROM users WHERE hire_date

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

      【讨论】:

      • DATETIME 不存储为浮点数。它存储为 2 个整数,一个是日期,另一个是时间。我认为在这里使用 float 绝对没有意义。由于浮点舍入问题,它可能添加的只是不正确的结果。
      • 顺便说一句:要查看此内容,您可以使用SELECT DATEADD(SECOND,CAST(SUBSTRING(CAST(GETDATE() as binary(8)),5,4) AS INT)/300.00,0)
      猜你喜欢
      • 2019-05-26
      • 1970-01-01
      • 1970-01-01
      • 2021-11-15
      • 1970-01-01
      • 2018-04-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多