На самом деле я уже решил проблему, но я пытаюсь понять, почему проблема возникла, потому что, насколько я понимаю, у нее нет причин. У меня есть довольно большой запрос, который я запускаю, чтобы подготовить таблицу с некоторыми часто используемыми комбинациями. Как правило, он содержит данные только за 2 года. Иногда буду реконструировать. Делая это, я подправил запрос, чтобы добавить больше информации, но неожиданно результат больше не соответствовал старому запросу. Сравнивая старый с новым, я заметил несколько отсутствующих заказов. Удивительно, но даже после удаления измененных частей результаты не совпали.
В конечном итоге я отследил проблему до моего предложения WHERE, что отличалось от того, как я делал это в прошлый раз.
Тип столбца orderdate, который я просматриваю, имеет тип (datetime, null)
Один из заказов, который был опущен, имел следующую дату:
2018-12-23 20:58:52.383
Заказ, который был включен, имел следующую дату:
2019-01-28 15:20:49.107
Это выглядит точно так же для меня.
Весь запрос такой же, за исключением предложения WHERE. Мой оригинал, где был:
WHERE DATEPART(yyyy,tbOrder.[OrderDate]) >= DATEPART(yyyy,GETDATE()-2)
Мое новое где сейчас:
WHERE tborder.[OrderDate] >= DATEADD(yy, DATEDIFF(yy, 0, GETDATE())-2, 0)
Мы будем очень признательны за любую помощь в понимании того, почему в исходном предложении where пропущены некоторые строки.
Спасибо, что указали в кодовых скобках, не смог разобраться в интерфейсе. Но я нашел это сейчас. Можете ли вы сказать мне, какие еще образцы данных вы ищете? Хотите больше примеров свиданий? Или полный комплект колонок?
Первый запрос возвращает строки за текущий год и не может использовать преимущества индексов. Другие все строки с 1 января два года назад и используют индексы на OrderDate
. Оба запроса выглядят странно. Чего ты хочешь, фактически? Кстати, такие запросы становятся много проще, когда вы используете таблицу календаря.
Вы можете легко проверить, что возвращает каждое выражение, с помощью оператора SELECT
: select DATEPART(yyyy,GETDATE()-2), DATEADD(yy, DATEDIFF(yy, 0, GETDATE()) - 2, 0)
Результаты совершенно разные в каждом случае.
Потому что вы делаете две разные вещи. Первый предикат,
WHERE DATEPART(yyyy,tbOrder.[OrderDate]) >= DATEPART(yyyy,GETDATE()-2)
Возьмите все даты заказов, которые больше года, за позавчера или за два дня до этого. Обратите внимание, что -2
находится внутри скобок.
Второй предикат,
WHERE tborder.[OrderDate] >= DATEADD( yy, DATEDIFF( yy, 0, GETDATE() ) - 2, 0)
Возьмите все даты заказов больше двух лет назад, т. Е. datediff(yy,startdate,enddate)
вернет результат года разницы между сегодняшним днем и начальным значением для date
типа данных, которое равно 1900-01-01
. Затем добавьте это, -2
, к 1900-01-01
. Второе выражение имеет вид:
1900 + ( 201X - 1898 )
Я упростил 1900 - 2 = 1898.
DATEPART(yyyy,GETDATE()-2)
возвращает текущий год, а не позавчера. Второй возвращается 1 января два года назад
@PanagiotisKanavos да, я имел в виду позавчерашний год. Я собираюсь отредактировать это, чтобы было ясно.
Спасибо! Я не могу поверить, что мне понадобилось столько времени, чтобы заметить случайную скобку, я даже попросил нашего местного ИТ-специалиста взглянуть на нее, и он ее проглядел. Я чувствую одновременно и облегчение, и невероятную глупость. :) WHERE DATEPART(yyyy,tbOrder.[OrderDate]) >= DATEPART(yyyy,GETDATE() ) -2
Обычно я так и делаю, результат тот же. Со скобкой перед -2.
@RoelDyky вообще нет причин писать такое сложное выражение
@RoelDyky рад быть полезным, когда я увидел -2
внутри скобок, первое, что пришло мне в голову, это то, что, вероятно, это была ошибка. Потому что, если нет, два предиката одинаково оцениваются как истинные в обоих случаях.
Два выражения возвращают совершенно разные вещи, поэтому неудивительно, что результаты будут разными. Первый возвращает год ток в виде числа (или, если быть точным, позавчерашний год). Второй возвращается 1 января два года назад.
Вы можете поместить оба выражения в запрос SELECT, чтобы увидеть, что они возвращают:
select DATEPART(yyyy,GETDATE()-2), DATEADD(yy, DATEDIFF(yy, 0, GETDATE()) - 2, 0)
Результат:
2019 2017-01-01 00:00:00.000
Оба выражения более сложны, чем они должны быть. Условие первый также снизит производительность, поскольку DATEPART(yyyy,tbOrder.[OrderDate])
не позволяет серверу использовать любые индексы, охватывающие OrderDate
.
Вопрос не объясняет, что вы на самом деле хотите вернуть. Если вы хотите вернуть все строки в текущем году, вы можете использовать:
Where
OrderDate >=DATEFROMPARTS( YEAR(GETDATE()) ,1,1) and
OrderDate < DATEFROMPARTS( YEAR(GETDATE()) + 1,1,1)
То же самое можно использовать для поиска строк за два года до этого:
Where
OrderDate >= DATEFROMPARTS( YEAR(GETDATE()) -2 ,1,1) and
OrderDate < DATEFROMPARTS(YEAR(GETDATE()) - 1,1,1)
Все строки с 1 января два года назад:
Where OrderDate >= DATEFROMPARTS( YEAR(GETDATE()) -2 ,1,1)
Все эти запросы могут использовать индексы, охватывающие OrderDate
.
Запросы диапазона дат становятся много проще, если вы используете Календарный стол. Календарная таблица — это таблица, которая содержит, например, даты за 50 или 100 лет с дополнительными столбцами для месяца, дня месяца, номера недели, дня недели, квартала, семестра, названий месяцев и дней, , длинные свидания и т.д.
Это делает ежегодные, ежемесячные или еженедельные запросы такими же простыми, как объединение с таблицей календаря и фильтрация на основе нужного месяца или периода.
В этом случае получение строк двумя годами ранее будет выглядеть так:
From Orders inner Join Calendar on OrderDate=Calendar.Date
Where Calendar.Year=YEAR(GETDATE())-2
Это может выглядеть не так впечатляюще, но как насчет Q2 два года назад?
From Orders inner Join Calendar on OrderDate=Calendar.Date
Where Calendar.Year=YEAR(GETDATE())-2 and Quarter=2
Два года назад, тот же квартал
From Orders inner Join Calendar on OrderDate=Calendar.Date
Where Calendar.Year=YEAR(GETDATE())-2 and Quarter=DATEPART(q,GETDATE())
Получение итогов за текущий квартал за последние два года:
SELECT Year,Quarter,SUM(Total) QuarterTotal
From Orders inner Join Calendar on OrderDate=Calendar.Date
Where Calendar.Year > YEAR(GETDATE())-2 and Quarter=DATEPART(q,GETDATE())
GROUP BY Calendar.Year
Я не знал о том, что datepart возится с индексами, оглядываясь назад, это кажется логичным. Спасибо за прекрасное объяснение и советы. У меня есть таблица календаря для использования в другом инструменте, но я никогда не думал об использовании ее для выбора внутренних соединений. Цель состояла в том, чтобы получить 2 полных года истории в подготовленной таблице.
Пожалуйста, предоставьте нам образцы данных. Оттуда результаты запроса 1 и результаты запроса 2...