sql >> Database >  >> RDS >> Sqlserver

De recursieve CTE-beëindigingscontrole begrijpen

Hier is een beter voorbeeld met datums. Stel dat we een tabel met datums willen maken. 1 rij voor elke maand voor het jaar 2017. We creëren een @startDate als het anker en @endDate als terminator. We hebben deze ingesteld op 12 maanden uit elkaar, omdat we een enkel jaar willen. Dan wordt de recursie een maand toegevoegd via de DATEADD functie naar de @startDate totdat de terminator is gevonden in de WHERE clausule. We weten dat er 11 recursies nodig zijn om 12 maanden te bereiken... dat wil zeggen 11 maanden + de startdatum. Als we de MAXRECURSION tot iets minder dan 11, dan zal het mislukken aangezien er 11 nodig zijn om te voldoen aan de WHERE clausule in onze recursieve CTE , dat is de 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

Voor je vraag zou een simpele join voldoende zijn.

select 
  firstName
  ,lastName
  ,orderDate
  ,productID
from
  customers c
inner join
  orders o on o.customerID = c.id

Ik zie echter dat u dit in een vreemd formaat probeert terug te geven, wat moet worden afgehandeld in welke rapportagetoepassing u ook gebruikt. Dit zou je dichtbij brengen zonder recursie.

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



  1. SELECT MySQL-veld dat een subtekenreeks bevat

  2. MySQL Groeperen op en groeperen op nulwaarden overslaan

  3. PostgreSQL/performance één algemene cursor of maak voor elke query

  4. Fout bij het aanroepen van Java vanuit PL/SQL