Как я могу написать предложение where в SQL для фильтрации столбца DATETIME по времени дня? - PullRequest
2 голосов
/ 02 апреля 2009

У меня есть данные с меткой времени в столбце DATETIME, и я хочу отфильтровать их до набора записей, где DATETIME находится между 9:30 и 17:30 для любого дня. Какой лучший способ сделать это?

ОБНОВЛЕНИЕ: изменено, потому что мне нужна точность до минуты, а не только часа. Извините за это.

Ответы [ 8 ]

2 голосов
/ 02 апреля 2009

Вы всегда можете написать ее как пользовательскую функцию, особенно если вам нужно делать это регулярно

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 голос
/ 02 апреля 2009

Аналогично приведенному выше коду, просто добавьте DATEPART (mi, column) для вашего требования MINUTE

Однако обратите внимание, что это снизит производительность, так как функции в столбцах будут избегать использования индекса (без sargeable)

Если вы используете SQL 2008, у них есть новые типы данных DATE и TIME, которые вы можете использовать для сравнения. Если нет, то в SQL 2005 возможно вы можете создать вычисляемые столбцы для части TIME и использовать ее

0 голосов
/ 02 апреля 2009
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.

0 голосов
/ 02 апреля 2009

Объедините часы и минуты и сравните диапазон.

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
0 голосов
/ 02 апреля 2009

Либо как то так:

   ...
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'

Никакой индекс не может быть использован для этого любого из этих запросов. Чтобы использовать индекс, предварительно рассчитайте значения тем или иным способом и сохраните их в индексированном столбце.

0 голосов
/ 02 апреля 2009
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
0 голосов
/ 02 апреля 2009
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 вечера, но вы должны быть в состоянии настроить при необходимости. Также имейте в виду, что он не может эффективно использовать индексы для этого поиска. Если время дня часто будет использоваться для поиска или вычислений, вы можете рассмотреть возможность его разделения и сохранения ДАТЫ и ВРЕМЕНИ в виде двух столбцов.

0 голосов
/ 02 апреля 2009
SELECT * 
FROM table1 
WHERE 
    (DatePart(hh, DateColumn) >= 9 and DatePart(mm, DateColumn) >= 30)
        AND (DatePart(hh, DateColumn) <= 17 AND DatePart(mm, DateColumn) <= 30)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...