Her er et bedre eksempel på at bruge datoer. Antag, at vi vil bygge en tabel med datoer. 1 række for hver måned i år 2017. Vi opretter en @startDate
som anker og @endDate
som terminator. Vi sætter disse til 12 måneders mellemrum, da vi ønsker et enkelt år. Derefter vil rekursionen tilføje en måned via DATEADD
funktion til @startDate
indtil terminatoren er opfyldt i WHERE
klausul. Vi ved, at det vil tage 11 rekursioner at ramme 12 måneder... altså 11 måneder + startdatoen. Hvis vi indstiller MAXRECURSION
til noget mindre end 11, så vil det mislykkes, da 11 er nødvendige for at opfylde WHERE
klausul i vores rekursive CTE
, det er terminatoren..
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
Til din forespørgsel ville en simpel joinforbindelse være tilstrækkelig.
select
firstName
,lastName
,orderDate
,productID
from
customers c
inner join
orders o on o.customerID = c.id
Jeg kan dog se, at du forsøger at returnere dette i et mærkeligt format, som skal håndteres i hvilken som helst rapporteringsapplikation, du bruger. Dette ville bringe dig tæt på uden gentagelser.
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