Нужна помощь с SQL-запросом при выборе диапазонов дат из таблицы квартальных периодов - PullRequest
1 голос
/ 07 июля 2010

У меня есть таблица с именем Периоды , которая выглядит так

PeriodID | PeriodYear | PeriodQuarter

7 |2009 |1

8 |2009 |2

9 |2009 |3

10 |2009 |4

11 |2010 |1

12 |2010 |2

Каждая строка в таблице представляет 1 из 4 кварталов года (например, трехмесячные школьные условия).Например, первая строка представляет период 1 2009 года (т. Е. Диапазон дат 1 января 2009 г. - 31 марта 2009 г.)

Теперь мне нужно написать запрос, который выбирает строки / периоды из таблицы выше, где период происходит между2 диапазона дат, согласно следующему псевдокоду.

select *
from Periods
where Period is between @startDate and @endDate

Запрос будет использоваться внутри табличной функции dbo.GetPeriodsFromDateRange, а @startDate и @endDate являются параметрами для функции.

Я застрял и не могу понять, как это сделать. Пожалуйста, помогите. Это относится к T-SQL (MS SQL Server 2000/2005)

Ответы [ 3 ]

5 голосов
/ 07 июля 2010

Попробуйте

select *
from Periods
where  dateadd(qq,PeriodQuarter-1,dateadd(yy,PeriodYear -1900,0)) 
between @startDate and @endDate
2 голосов
/ 16 июля 2010

Возможен поиск вместо сканирования:

SELECT *
FROM Periods
WHERE
   PeriodYear BETWEEN Year(@startdate) AND Year(@enddate)
   AND PeriodYear * 4 + PeriodQuarter
      BETWEEN Year(@startdate) * 4 + DATEPART(Quarter, @startdate)
      AND Year(@startdate) * 4 + DATEPART(Quarter, @enddate)

Объяснение :

Я сочиняю новое, масштабированное целое число из двух составных частей,год и квартал, рассматривая каждую комбинацию года и квартала как одно число.

Представьте себе, что я сделал это следующим образом:

AND PeriodYear + (PeriodQuarter - 1) / 4.0
   BETWEEN Year(@startdate) + (DATEPART(Quarter, @startdate) - 1) / 4.0
   AND Year(@startdate) + (DATEPART(Quarter, @enddate) - 1) / 4.0

Называя мое первоначальное выражение "Mult" иэтот новый "Div", вот несколько лет и кварталов, и что эти выражения будут оценивать:

Year Qtr Div     Mult
2009 1   2009.00 8037
2009 2   2009.25 8038
2009 3   2009.50 8039
2009 4   2009.75 8040
2010 1   2010.00 8041
2010 2   2010.25 8042
2010 3   2010.50 8043

Так что теперь, если мы запустим предложение WHERE для этих строк:

WHERE Div BETWEEN 2009.25 AND 2010.00

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

Причина, по которой я использую два условия, начиная только с года, состоит в том, чтобы сделать запрос саргнируемым.Мы хотим выполнить поиск, основываясь только на году, что невозможно, если мы умножим его на 4 или выполним другие математические расчеты.Таким образом, мы сначала сканируем только правильные годы, а затем настраиваем его, чтобы исключить все кварталы, которые не должны быть в результате.

Другой вариант - добавить вычисляемый столбец и добавить к нему индекс.Это не потребует внесения каких-либо изменений в вставку или обновление кода (при условии, что они правильно используют списки столбцов), но позволит вам выполнять математику обычного диапазона по вашему желанию.

0 голосов
/ 07 июля 2010

Я хотел бы добавить еще 2 столбца в таблицу ...

StartDate и EndDate - они будут хранить дату начала каждого периода изаканчивается (т. е. в вашем примере: StartDate = 1 января 2009 г. и EndDate = 31 марта 2009 г.)

Это даст вам большую гибкость, если кварталы определены не так, как вы предлагали.

Если вы это сделаетепосле этого запрос становится довольно простым ...

select *
from Periods
where @startDate<Periods.StartDate and @endDate>Periods.EndDate

Это предполагает, что вы хотите включить только периоды, которые полностью инкапсулированы между @StartDate и @EndDate.Если вы хотите, чтобы периоды перекрывались, попробуйте что-то вроде ...

select *
from Periods
where @EndDate>Periods.StartDate and @StartDate<Periods.EndDate
...