Oto lepszy przykład z użyciem dat. Załóżmy, że chcemy zbudować tabelę dat. 1 wiersz na każdy miesiąc w roku 2017. Tworzymy @startDate
jako kotwica i @endDate
jako terminator. Ustawiliśmy je na 12 miesięcy, ponieważ chcemy jednego roku. Następnie rekursja doda jeden miesiąc za pomocą DATEADD
funkcji do @startDate
dopóki terminator nie zostanie spełniony w WHERE
klauzula. Wiemy, że potrzeba 11 rekurencji, aby osiągnąć 12 miesięcy... czyli 11 miesięcy + data rozpoczęcia. Jeśli ustawimy MAXRECURSION
do wartości mniejszej niż 11, to się nie powiedzie, ponieważ 11 jest potrzebnych do wypełnienia WHERE
klauzula w naszym rekurencyjnym CTE
, czyli terminator..
declare @startDate datetime = '20170101'
declare @endDate datetime = '20171201'
;WITH Months
as
(
SELECT @startDate as TheDate --anchor
UNION ALL
SELECT DATEADD(month, 1, TheDate) --recursive
FROM Months
WHERE TheDate < @endDate --terminator... i.e. continue until this condition is met
)
SELECT * FROM Months OPTION (MAXRECURSION 10) --change this to 11
W przypadku zapytania wystarczy proste sprzężenie.
select
firstName
,lastName
,orderDate
,productID
from
customers c
inner join
orders o on o.customerID = c.id
Widzę jednak, że próbujesz zwrócić to w dziwnym formacie, który powinien być obsługiwany w dowolnej aplikacji do raportowania, której używasz. Dzięki temu będziesz blisko bez rekurencji.
with cte as(
select
firstName
,lastName
,orderDate
,productID
,dense_rank() over(order by c.id) as RN
from
customers c
inner join
orders o on o.customerID = c.id)
select distinct
firstName
,lastName
,null
,null
,RN
from
cte
union all
select
''
,''
,orderDate
,productID
,RN
from
cte
order by RN, firstName desc