2017-10-20 19 views
3

je suis en train de faire pivoter deux Col. aux lignesle pivotement deux colonnes en utilisant SQL dynamique

NO Code Amount 
-- ---- ------- 
1 61 1714.00 
1 23 95.79 
1 80 31.00 
1 61 45.00 
2 61 1714.00 
2 23 95.79 
3 80 31.00 
4 61 45.00 
4 61 1714.00 
4 23 95.79 
4 80 31.00 
4 61 45.00 

Je veux faire pivoter le code et le montant COLS dynamiquement à comme ci-dessous et ajouter des suffixes aux noms de colonnes

NO Code_01 Amount_01 Code_02 Amount_02 Code_03 Amount_03 Code_04 Amount_04 
1 61  1714.00 23  95.79  80  31.00  61  45.00 
2 61  1714.00 23  95.79  - - - - 
... 

j'ai commencé à faire une colonne mais en cours d'exécution dans les erreurs ... Toute aide avec cela?

DECLARE @cols NVARCHAR(MAX) 
    ,@sql NVARCHAR(MAX) 

SET @cols = STUFF((
      SELECT DISTINCT ',' + QUOTENAME(CODE) 
      FROM Table1 
      ORDER BY 1 
      FOR XML PATH('') 
       ,TYPE 
      ).value('.', 'NVARCHAR(MAX)'), 1, 1, '') 
SET @sql = 'SELECT NO, ' + @cols + ' 
       FROM 
      (
       SELECT NO 
       FROM Table1 
      ) s 
      PIVOT 
      (
       MAX(Amount) FOR Code IN (' + @cols + ') 
      ) p' 

--print(@sql) 

EXECUTE(@sql) 

Répondre

3

utilisant SQL dynamique pour générer des instructions conditionnelles d'agrégation pour obtenir les max() par row_number() (divisé par No) au lieu de plusieurs pivots:

declare @cols nvarchar(max); 
declare @sql nvarchar(max); 
select @cols = stuff((
    select distinct 
     char(10)+' , ' 
     + quotename('Code_'+rn)+' = max(case when rn = '+rn+' then Code end)' 
     + char(10)+' , ' 
     + quotename('Amount_'+rn)+' = max(case when rn = '+rn+' then Amount end)' 
    from (
     select No, Code 
     , rn = convert(varchar(10),row_number() over (partition by No order by Code)) 
     from Table1 
    ) s 
    order by 1 
    for xml path (''), type).value('.','nvarchar(max)') 
    ,1,0,''); 

select @sql =' 
select No '[email protected]+' 
from (
    select No, Code, Amount 
    , rn = row_number() over (partition by No order by Code) 
    from Table1 
) sub 
group by No'; 

select @sql; 
exec(@sql); 

rextester Démo: http://rextester.com/ALTID91433

code généré:

select No 
    , [Code_1] = max(case when rn = 1 then Code end) 
    , [Amount_1] = max(case when rn = 1 then Amount end) 
    , [Code_2] = max(case when rn = 2 then Code end) 
    , [Amount_2] = max(case when rn = 2 then Amount end) 
    , [Code_3] = max(case when rn = 3 then Code end) 
    , [Amount_3] = max(case when rn = 3 then Amount end) 
    , [Code_4] = max(case when rn = 4 then Code end) 
    , [Amount_4] = max(case when rn = 4 then Amount end) 
    , [Code_5] = max(case when rn = 5 then Code end) 
    , [Amount_5] = max(case when rn = 5 then Amount end) 
from (
    select No, Code, Amount 
    , rn = row_number() over (partition by No order by Code) 
    from Table1 
) sub 
group by No 

résultats:

+----+--------+----------+--------+----------+--------+----------+--------+----------+--------+----------+ 
| No | Code_1 | Amount_1 | Code_2 | Amount_2 | Code_3 | Amount_3 | Code_4 | Amount_4 | Code_5 | Amount_5 | 
+----+--------+----------+--------+----------+--------+----------+--------+----------+--------+----------+ 
| 1 |  23 | 95.79 | 61  | 45.00 | 61  | 1714.00 | 80  | 31.00 | NULL | NULL  | 
| 2 |  23 | 95.79 | 61  | 1714.00 | NULL | NULL  | NULL | NULL  | NULL | NULL  | 
| 3 |  80 | 31.00 | NULL | NULL  | NULL | NULL  | NULL | NULL  | NULL | NULL  | 
| 4 |  23 | 95.79 | 61  | 45.00 | 61  | 45.00 | 61  | 1714.00 | 80  | 31.00 | 
+----+--------+----------+--------+----------+--------+----------+--------+----------+--------+----------+ 
+0

SqlZim - avez-vous une application qui formate votre jeu de résultats afin que vous puissiez la publier en ligne? –

+2

@ MarkKram J'utilise https://senseful.github.io/text-table/ – SqlZim

2

Vous pouvez créer dynamiquement une requête PIVOT comme celui-ci.

DECLARE @ColumnNames NVARCHAR(MAX) ='' 
SELECT @ColumnNames = @ColumnNames + ', ' + QUOTENAME ('Code_' + RN) + ', ' + QUOTENAME ('Amount_' + RN ) 
FROM (SELECT DISTINCT RN = RIGHT('0' + CONVERT(varchar, ROW_NUMBER() OVER(PARTITION BY [NO] ORDER BY [NO])),2) FROM Table1) AS T 
SET @ColumnNames = STUFF(@ColumnNames,1,1,'') 


DECLARE @SqlText NVARCHAR(MAX) 
SET @SqlText = 'SELECT * FROM 
        (SELECT [NO], ''Code_'' + RIGHT(''0'' + CONVERT(varchar, ROW_NUMBER() OVER(PARTITION BY [NO] ORDER BY [NO])),2) Col, CONVERT(VARCHAR,Code) Value FROM Table1 
         UNION ALL 
        SELECT [NO], ''Amount_'' + RIGHT(''0'' + CONVERT(varchar, ROW_NUMBER() OVER(PARTITION BY [NO] ORDER BY [NO])),2) Col, CONVERT(VARCHAR,Amount) Value FROM Table1) SRC 
        PIVOT (MAX(Value) FOR Col IN (' + @ColumnNames + ')) PVT' 

print @SqlText 
EXEC sp_executesql @SqlText 

requête Produit:

SELECT * FROM 
(SELECT [NO], 'Code_' + RIGHT('0' + CONVERT(varchar, ROW_NUMBER() OVER(PARTITION BY [NO] ORDER BY [NO])),2) Col, CONVERT(VARCHAR,Code) Value FROM Table1 
    UNION ALL 
SELECT [NO], 'Amount_' + RIGHT('0' + CONVERT(varchar, ROW_NUMBER() OVER(PARTITION BY [NO] ORDER BY [NO])),2) Col, CONVERT(VARCHAR,Amount) Value FROM Table1) SRC 
PIVOT (MAX(Value) FOR Col IN ([Code_01], [Amount_01], [Code_02], [Amount_02], [Code_03], [Amount_03], [Code_04], [Amount_04], [Code_05], [Amount_05])) PVT 

Résultat:

NO Code_01 Amount_01 Code_02 Amount_02 Code_03 Amount_03 Code_04 Amount_04 Code_05 Amount_05 
--- ------- --------- ------- --------- ------- --------- ------- --------- ------- --------- 
1 61  1714.00 23  95.79  80  31.00  61  45.00  NULL  NULL 
2 61  1714.00 23  95.79  NULL  NULL  NULL  NULL  NULL  NULL 
3 80  31.00  NULL  NULL  NULL  NULL  NULL  NULL  NULL  NULL 
4 61  45.00  61  1714.00 23  95.79  80  31.00  61  45.00