sql >> Base de Datos >  >> RDS >> Sqlserver

Comprensión de la verificación de terminación de CTE recursiva

Aquí hay un mejor ejemplo usando fechas. Supongamos que queremos construir una tabla de fechas. 1 fila por cada mes del año 2017. Creamos un @startDate como ancla y @endDate como terminador. Los establecemos con 12 meses de diferencia, ya que queremos un solo año. Luego, la recursión agregará un mes a través de DATEADD función al @startDate hasta que se cumpla el terminador en WHERE cláusula. Sabemos que se necesitarán 11 recursiones para alcanzar los 12 meses... es decir, 11 meses + la fecha de inicio. Si configuramos el MAXRECURSION a menos de 11, entonces fallará ya que se necesitan 11 para cumplir con WHERE cláusula en nuestro recursivo CTE , ese es el terminador..

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

Para su consulta, bastaría con una simple combinación.

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

Sin embargo, veo que está tratando de devolver esto en un formato extraño, que debe manejarse en cualquier aplicación de informes que esté utilizando. Esto lo acercaría sin recurrencia.

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