Séparer les lignes de la table à l'aide du CTE

J'ai les lignes suivantes à partir d'une table dans SQL Server 2008 R2

+-------------------------------------------+ | ID EntryType dt price | +-------------------------------------------+ | 14 4 2012-11-07 0.025000 | | 16 5 2012-11-07 0.026000 | | 18 6 2012-11-07 0.026000 | | 20 7 2012-11-07 0.026000 | +-------------------------------------------+ 

Ce que je voudrais faire est de répartir les lignes en fonction du EntryType (le EntryType ne change pas)

 For EntryType = 4 (1 row) For EntryType = 5 (2 row) For EntryType = 6 (3 row) For EntryType = 7 (9 row) 

et le champ dt sera incrémenté (dans un intervalle de mois), de sorte que la sortie ressemble à ceci:

 +-----------+-----------+-------+ | EntryType | dt | Price | +-----------+-----------+-------+ | 4 | 11/7/2012 | 0.024 | | 5 | 12/7/2012 | 0.025 | | 5 | 1/7/2013 | 0.025 | | 6 | 2/7/2013 | 0.026 | | 6 | 3/7/2013 | 0.026 | | 6 | 4/7/2013 | 0.026 | | 7 | 5/7/2013 | 0.027 | | 7 | 6/7/2013 | 0.027 | | 7 | 7/7/2013 | 0.027 | | 7 | 8/7/2013 | 0.027 | | 7 | 9/7/2013 | 0.027 | | 7 | 10/7/2013 | 0.027 | | 7 | 11/7/2013 | 0.027 | | 7 | 12/7/2013 | 0.027 | | 7 | 1/7/2014 | 0.027 | +-----------+-----------+-------+ 

Est-ce possible avec CTE et SQL?

Voici un moyen de le faire dans un CTE récursif :

 ;with RecordCounts as ( -- Establish row counts for each EntryType select 4 as EntryType, 1 as RecordCount union all select 5, 2 union all select 6, 3 union all select 7, 9 ), PricesCte as ( -- Get initial set of records select ID, p.EntryType, (select min(dt) from MyTable) as dt, price, 1 as RecordNum from MyTable p join RecordCounts c on p.EntryType = c.EntryType -- Only get rows where we've established a RecordCount -- Add records recursively according to RecordCount union all select ID, p.EntryType, dt, price, RecordNum + 1 from PricesCte p join RecordCounts c on p.EntryType = c.EntryType where RecordNum + 1 <= c.RecordCount ) select EntryType, dateadd(mm, row_number() over (order by EntryType, ID) - 1, dt) as dt, price from PricesCTE order by EntryType option (maxrecursion 0) -- Infinite recursion, default limit is 100 

Voici le SqlFiddle montrant ce travail.

Un certain nombre de choses:

  • Je pense qu'au fur et à mesure que le nombre d'loggings grimpe, cela pourrait mieux fonctionner en utilisant une table de pointage plutôt que de récursion pour multiplier les loggings. Vous devez vous joindre à la table Tally et avoir la clause where limitant les loggings en fonction du RecordCount
  • Je ne vois pas comment le prix est censé changer de l'input à la sortie.
  • Je ne sais pas où vous établissez RecordCount par EntryType, donc j'ai ajouté cela dans un autre CTE.
 ;WITH e (ID, EntryType, row, dt, Price, [Len]) AS ( SELECT ID, EntryType, CASE EntryType WHEN 4 THEN 1 WHEN 5 THEN 2 WHEN 6 THEN 3 WHEN 7 THEN 9 END AS row, dt, Price, 0 AS [Len] FROM dbo.your_table ), x (ID, EntryType, row, dt, Price, [Len]) AS ( SELECT ID, EntryType, row, dt, Price, 1 FROM e UNION ALL SELECT e.ID, e.EntryType, e.row, e.dt, e.Price, x.[Len] + 1 FROM e , x WHERE e.ID = x.ID AND e.row > x.[Len] ) SELECT EntryType, DATEADD(mm, ROW_NUMBER() OVER(ORDER BY EntryType)-1, dt) AS dt, Price FROM x ORDER BY EntryType 

La seule chose que je ne peux pas comprendre par quels critères pour recevoir le prix?

Démo sur SQL Fiddle

Je ne sais pas si cela peut être fait par CTE, car je ne peux pas dire de logique entre EntryType et # of row.

Pour la question, je pense qu'il est plus facile de build une table temporaire avec le nombre de lignes que vous voulez

 DECLARE @Entry TABLE(EntryType INT, seq INT) INSERT INTO @Entry (EntryType , seq) VALUES (4,1) ,(5,1) ,(5,2) ,(6,1) ... ,(7,1) .. ,(7,9) 

Après cela, une simple requête obtiendra le même résultat

 SELECT t.EntryType , DATEADD(MONTH,e.seq, t.dt) as dt,t.Price FROM YourTable t INNER JOIN @Entry e ON t.EntryType = e.EntryType