如何在SQL中编写where子句以按时间过滤DATETIME列?

时间:2009-04-02 15:35:23

标签: sql sql-server

我的数据带有DATETIME列的时间戳,我希望将其过滤到DAT​​ETIME在任何一天的上午9:30到下午5:30之间的记录集。最好的方法是什么?

更新:改变因为我需要精确到分钟,而不仅仅是小时。对不起。

8 个答案:

答案 0 :(得分:2)

您可以随时将其编写为用户定义函数,特别是如果您需要定期执行此操作

CREATE function  dbo.timepart (@date as SMALLDATETIME)
RETURNS SMALLDATETIME
AS
BEGIN
    RETURN @date - DATEADD(d, DATEDIFF(d,0,@date), 0)
END

然后像这样使用

SELECT * FROM table
WHERE dbo.timepart(date_field) BETWEEN '9:30' AND '17:30'

在SQL Server 2005中使用以下测试

DECLARE @dates TABLE (date DATETIME)

DECLARE @date DATETIME
SET @date = '20 MAR 2009'

WHILE @date < '22 MAR 2009'
    BEGIN
        INSERT INTO @dates VALUES(@date)
        SET @date = DATEADD(hour, 1, @date)
    END

SELECT * 
FROM
    @dates
WHERE
    dbo.timepart(date) BETWEEN '9:30' AND '17:30'

结果

date
-----------------------
2009-03-20 10:00:00.000
2009-03-20 11:00:00.000
2009-03-20 12:00:00.000
2009-03-20 13:00:00.000
2009-03-20 14:00:00.000
2009-03-20 15:00:00.000
2009-03-20 16:00:00.000
2009-03-20 17:00:00.000
2009-03-21 10:00:00.000
2009-03-21 11:00:00.000
2009-03-21 12:00:00.000
2009-03-21 13:00:00.000
2009-03-21 14:00:00.000
2009-03-21 15:00:00.000
2009-03-21 16:00:00.000
2009-03-21 17:00:00.000

答案 1 :(得分:1)

与上述代码类似,只需为您的MINUTE要求添加DATEPART(mi,列)

但是,请注意,这将会影响性能,因为列上的函数将避免使用索引(非sargeable)

如果您使用的是SQL 2008,则可以使用DATE和TIME新数据类型进行比较。如果没有,在SQL 2005中,也许您可​​以为TIME部分创建计算列并使用它

答案 2 :(得分:0)

SELECT * 
FROM table1 
WHERE 
    (DatePart(hh, DateColumn) >= 9 and DatePart(mm, DateColumn) >= 30)
        AND (DatePart(hh, DateColumn) <= 17 AND DatePart(mm, DateColumn) <= 30)

答案 3 :(得分:0)

SELECT
     *
FROM
     My_Table
WHERE
     DATEPART(hh, some_date) BETWEEN 9 AND 16 OR
     (DATEPART(hh, some_date) = 17 AND DATEPART(mm, some_date) = 0...)

可替换地:

SELECT
     *
FROM
     My_Table
WHERE
     DATEADD(dd, 1-DATEPART(dd, some_date),
          DATEADD(mm, 1-DATEPART(mm, some_date),
               DATEADD(yy, 1900-DATEPART(yy, some_date), some_date)))
     BETWEEN @start_time AND @end_time

只需使用所需时间制作@start_time和@end_time 1900-01-01。

这将排除05:00:00.000 PM,但您应该可以根据需要进行调整。另请注意,它无法有效地使用索引进行此搜索。如果时间通常用于搜索或计算,您可以考虑将其分开并将DATE和TIME保持为两列。

答案 4 :(得分:0)

SELECT *
FROM your_table
WHERE (DATEPART(hh, date_column) = 9 AND DATEPART(mi, date_column) >= 30)
    OR (DATEPART(hh, date_column) = 17 AND DATEPART(mi, date_column) <= 30)
    OR DATEPART(hh, date_column) BETWEEN 10 AND 16

答案 5 :(得分:0)

这样的事情:

   ...
WHERE
  (DATEPART(hh, some_date) BETWEEN 10 AND 16)
  OR
  (DATEPART(hh, some_date) = 9 AND DATEPART(mi, some_date) >= 30)
  OR
  (DATEPART(hh, some_date) = 17 AND DATEPART(mi, some_date) <= 30)

或者:

   ...
WHERE
  LEFT(CONVERT(VARCHAR, some_date, 8), 5) >= '09:30' AND
  LEFT(CONVERT(VARCHAR, some_date, 8), 5) <= '17:30'

甚至:

   ...
WHERE
  LEFT(CONVERT(VARCHAR, some_date, 8), 5) BETWEEN '09:30' AND '17:30'

任何这些查询都不能使用索引。要使用索引,请以某种方式预先计算值,并将它们存储在索引列中。

答案 6 :(得分:0)

连接小时和分钟并比较范围。

with Result as (
    select  [Time] = cast(cast(datepart(hh, AuditDate) as varchar) + 
            cast(datepart(mi, AuditDate) as varchar) as int), *
    from    AuditTable
)
select  *
from    Result
where   [Time] between 930 and 1730

答案 7 :(得分:0)

Select * from tbl 
where ts between 
convert(datetime,convert(varchar,ts, 101)) + convert(datetime,'9:30 am') 
And Convert(datetime,convert(varchar,ts,101)) + convert(datetime,'5:30 pm')

我认为这将使用索引。我无法测试,我发布了这个用ipod

[从我的电脑编辑]

create function  dbo.DaysTime(@date as datetime, @time datetime) 
returns datetime 
as
begin

   /* datediff approach on scraping the 
   time part of datetime: inspired by Russ Cam */


   return dateadd(d, datediff(d, 0, @d), 0)/*the date's day*/ + @time

end


select * from tbl where ts 
between dbo.DaysTime(ts, '9:30 AM') and dbo.DaysTime(ts, '5:30 PM')

这仍然会使用索引,因为我们没有在where条件的左侧放置一个表达式。