Распечатать все даты текущего года на SQL Server 2008R2 - PullRequest
3 голосов
/ 16 августа 2011

Следующие коды будут печатать все даты в течение текущего года на SQL Server 2008R2

with x (dy, yr)
 as (
select dy, year (dy) yr
from (
     select getdate () - datepart (dy, getdate ()) + 1 dy
     -- the first date of the current year
     ) tmp1
union all
select dateadd (dd, 1, dy), yr
from x
where year (dateadd (dd, 1, dy)) = yr
 )
select x.dy
from x
option (maxrecursion 400)     

Но есть некоторые моменты, которые я не могу понять

  1. Насколько я вижу, первая дата должна была быть напечатана 400 раз, отфильтрованы ли все повторы?
  2. когда я изменяю 400 на 364, возвращается следующая ошибка:

[Err] 42000 - [SQL Server] Оператор завершен. Максимум рекурсия 363 была исчерпана до завершения оператора.

Но как процессор узнает, когда оператор завершится?

Ответы [ 2 ]

4 голосов
/ 16 августа 2011

Здесь вы имеете дело с рекурсивным CTE .Вероятно, вам следует просто узнать больше о том, как это работает.

В основном,

  • Он получает первый набор строк из якорной части (первый SELECT, левая часть UNION ALL).

  • Этот набор строк становится псевдонимом x во втором SELECT (правая часть UNION ALL),называемая рекурсивная часть .

  • Рекурсивная часть создает другой набор строк на основе x, , который становится новым x на следующей итерации.То есть не объединенный набор строк исходного x и последнего набора результатов становится новым x, но только последним набором результатов.

  • Предыдущий шаг повторяется снова для нового x, и цикл продолжается до тех пор, пока одно из этих значений не станет истинным:

    • другая итерация не приводит к набору результатов;

    • достигнут предел MAXRECURSION.

Окончательный набор результатов состоит из всех наборов частичных результатов, полученных изобе части рекурсивного CTE.

Применение вышеуказанного к вашему конкретному запросу:

  • Первый SELECT создает одну строку, содержащую 1 st этого годаянваря (дата), и он становится первой x таблицей.

  • Для каждой строки x второй SELECT создает строку, содержащую соответствующую следующую дату если , то он принадлежит тому же году.Итак, первая итерация рекурсивной части фактически дает нам 2 и января.В соответствии с приведенным выше описанием, набор результатов становится новым x.

  • . Следующая итерация приводит к 3 rd января, следующая -4 th и т. Д.

  • Если значение параметра MAXRECURSION безопасно позволило нам прибыть в тот момент, когда x содержит 31 st декабря, затем другая итерация покажет, что следующий день фактически принадлежит другому году.Это приведет к созданию пустого набора строк, что, в свою очередь, приведет к прекращению выполнения рекурсивного CTE.

1 голос
/ 16 августа 2011

Это не ответ, это просто другой способ написания вашего sql.Андрей М оставил вам крутой ответ, вы должны отдать ему должное за правильный ответ.

;with x (dy) 
 as ( 
select dateadd(year, datediff(year, 0, getdate()), 0) dy 
union all 
select dy + 1 
from x 
where year (dy) = year(dy+1) 
) 
select x.dy 
from x 
option (maxrecursion 400) 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...