Группировать по дате и времени, игнорируя часть времени - PullRequest
5 голосов
/ 14 сентября 2011

Можно ли написать запрос Microsoft SQL, который будет группироваться по типу данных datetime, но игнорируя часть времени, такую ​​как часы и минуты?

Ответы [ 2 ]

12 голосов
/ 14 сентября 2011

Если вы используете SQL Server 2008, это просто.

GROUP BY CAST(YourCol AS Date)

Для предыдущих версий вы можете использовать

GROUP BY DATEDIFF(DAY, 0, YourCol)

Однако ни один из них не сможет использовать тот факт, что индекс на YourCol, упорядоченный по datetime, будет также упорядочен по date и, таким образом, использует агрегат потока без операции сортировки.

В SQL Server 2008+ вы можете рассмотреть возможность индексирования (date,time), а не datetime, чтобы упростить этот тип запроса.

Либо просто сохраняя его как два отдельных компонента и, возможно, предоставляя вычисляемый столбец, который объединяет части (datetime2 хранится так же, как date и time, так что это не будет занимать больше места за исключением случаев, когда дополнительный столбец помещает NULL_BITMAP в новый байт.).

CREATE TABLE T
(
YourDateCol date,
YourTimeCol time,
YourDateTimeCol AS  DATEADD(day, 
                            DATEDIFF(DAY,0,YourDateCol), 
                            CAST(YourTimeCol AS DATETIME2(7)))
/*Other Columns*/
)

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

Пример такого подхода

CREATE TABLE T
(
DT DATETIME2,
D AS CAST(DT AS DATE),
T AS CAST(DT AS TIME)
)

CREATE INDEX IX1 ON T(DT);

SELECT COUNT(*), 
       CAST(DT AS DATE)
FROM T
GROUP BY CAST(DT AS DATE)

CREATE INDEX IX2 ON T(D,T);

SELECT COUNT(*), 
       CAST(DT AS DATE)
FROM T
GROUP BY CAST(DT AS DATE)

DROP TABLE T

enter image description here

1 голос
/ 14 сентября 2011

Если у вас большая таблица и вы хотите, чтобы группировка выполнялась fast , вы не можете полагаться на группировку по выражению.

Создайте дополнительный столбец datetime в вашей таблице и заполните его триггером, который вычисляет базовую дату из вашей «реальной» даты:

UPDATE
  MyTable
SET
  EffectiveDate = DATEADD(DAY, 0, DATEDIFF(DAY, 0, t.RecordDate))
FROM
  MyTable t
  INNER JOIN inserted i ON i.RowID = t.RowID

Затем установите индекс на EffectiveDate, и группировка (и поиск) будут намного быстрее.

...