Каков наилучший способ получить результаты за 24 часа в T-SQL?

Я работаю над созданием диаграммы для своего клиента, и они хотят получить общее количество клиентов за 24 часа, 3 дня, 1 неделю, 1 месяц и т.д. Я честно не самый лучший с SQL, поэтому генерация этих запросов не является моей сильной стороной.

Что касается получения клиентами более 24 часов, я столкнулся с двумя заявлениями "where", которые могут работать, но я не уверен, какой из них лучше.

Первая версия:

WHERE DATEDIFF(hh,CreatedDate,GETDATE())>24

Вторая версия:

WHERE CreatedDate >= DATEADD(HH, -24, GETDATE())

Первая версия генерирует 21 строку, а вторая генерирует 17 строк (из одного набора данных, конечно), поэтому, очевидно, один более точен, чем другой. Я склоняюсь к первому, но я бы хотел, чтобы ваше мнение... пожалуйста.

Спасибо, Эндрю

Ответ 1

Избегайте первой версии. Во-первых, поскольку это отключает использование индекса. Вторая (функциональная) проблема с первой версией: DATEDIFF(HOUR...) возвращает все значения менее 25 часов. Попробуйте это для ясности:

SELECT DATEDIFF(HOUR, '2010-07-19 00:00:00', '2010-07-20 00:59:59.99')

Ответ 2

Первая версия не является точной.

WHERE DateDiff(hh, CreatedDate, GETDATE()) > 24

Это вернет значения где-то между 23.0001 часов назад и 24.9999 часов назад, потому что вы считаете "пересеченные границы", а не фактический 24-часовой период. Учтите, что с 1:59:59 до 2:00:00 это всего одна секунда, но DateDiff по часам вернет 1 час. Точно так же с 1:00:00 до 2:59:59 это почти 2 часа, но DateDiff по часам возвращает тот же 1 час.

Вторая версия верна.

WHERE CreatedDate >= DateAdd(hh, -24, GETDATE())

Вычитание 24 часов из текущей даты даст время ровно 24,0 часа назад, до миллисекунды. Таким образом, это вернет данные за 24 часа.

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

WHERE CreateDate >= DateAdd(hh, DateDiff(hh, 0, GETDATE()) - 24, 0)

Пример:

  • GetDate() = '20100720 17:52'
  • DateDiff(hh, 0, '20100720 17:52') = 969065
  • DateAdd(hh, 969065 - 24, 0) = '20100719 17:00'

и доказать это так же, как ваше первое выражение:

  • DateDiff(hh, '20100719 17:00', '20100720 17:52') = 24

Ответ 3

Возможно, это для каждого из ваших предложений where?

WHERE CreatedDate < GETDATE() AND CreatedDate >= DATEADD(hh, -24, GETDATE)

WHERE CreatedDate < GETDATE() AND CreatedDate >= DATEADD(day, -3, GETDATE)

WHERE CreatedDate < GETDATE() AND CreatedDate >= DATEADD(wk, -1, GETDATE)

WHERE CreatedDate < GETDATE() AND CreatedDate >= DATEADD(mm, -1, GETDATE)

А так как flo упомянул об индексах, просто убедитесь, что вы индексируете столбец CreateDate.