SQL Server Organize rows in columns by identification

dkqlctbz  于 2023-06-04  发布在  其他
关注(0)|答案(2)|浏览(122)

Data is
| ID | Name | TopNotch | Date |
| ------------ | ------------ | ------------ | ------------ |
| 100 | Dewey | 10 | 2011-01-01 |
| 100 | Dewey | 9 | 2011-01-02 |
| 102 | Huey | 8 | 2022-01-13 |
| 102 | Huey | 6 | 2022-02-13 |
| 102 | Huey | 4 | 2022-03-13 |
| 103 | Louie | 11 | 2012-08-10 |
| 103 | Louie | 12 | 2012-09-10 |
| 103 | Louie | 13 | 2012-10-10 |

Data should be organized horizontally, Goal:

IDNameTopNotch1Date1TopNotch2Date2TopNotch3Date3
1Dewey102011-01-0192011-01-02
2Huey82022-01-1362022-02-1342022-03-13
3Louie112012-08-10122012-09-10132012-10-10

Help.

vxqlmq5t

vxqlmq5t1#

It's probably not the best approach, but it may help you find a solution to your problem. The idea is to UNPIVOT the NetSum , Tax , Date columns (with the appropriate datatype cast) and after that PIVOT the result.

Data:

SELECT *
INTO Data
FROM (VALUES
   (1, 'Vlad', 'P', 1000,    2,      CONVERT(date, '2011-01-01')),
   (1, 'Vlad', 'P', 100,     0.2,    CONVERT(date, '2011-01-02')),
   (2, 'Volo', 'Z', 20,      2,      CONVERT(date, '2022-01-13')),
   (2, 'Volo', 'Z', 200,     20,     CONVERT(date, '2022-02-13')),
   (2, 'Volo', 'Z', 2000,    200,    CONVERT(date, '2022-03-13')),
   (3, 'Alex', 'L', 40,      0.4,    CONVERT(date, '2012-08-10')),
   (3, 'Alex', 'L', 400,     4,      CONVERT(date, '2012-09-10')),
   (3, 'Alex', 'L', 4000,    40,     CONVERT(date, '2012-10-10')),
   (4, 'Joe',  'B', 100000,  10000,  CONVERT(date, '2022-10-10')),
   (4, 'Joe',  'B', 1000000, 100000, CONVERT(date, '2023-10-10'))
) v (ID, FirstName, SurName, NetSum, Tax, Date)

Statement:

SELECT *
FROM (  
   SELECT ID, FirstName, SurName, CONCAT([Column], [Rn]) AS [Column], [Value]
   FROM (  
      SELECT 
         ID, FirstName, SurName, 
         CONVERT(varchar(50), NetSum) AS NetSum, 
         CONVERT(varchar(50), Tax) AS Tax, 
         CONVERT(varchar(50), Date) AS Date,
         ROW_NUMBER() OVER (PARTITION BY ID ORDER BY ID) AS [Rn]
      FROM Data
   ) d
   UNPIVOT (
      [Value] FOR [Column] IN ([NetSum], [Tax], [Date])
   ) u
) t
PIVOT (
   MAX([Value]) FOR [Column] IN (
      [NetSum1], [Tax1], [Date1], 
      [NetSum2], [Tax2], [Date2],
      [NetSum3], [Tax3], [Date3],
      [NetSum4], [Tax4], [Date4]
      -- Add more columns up to maximum ROW_NUMBER() per partition (probably 10)
  )
) p

Result:

IDFirstNameSurNameNetSum1Tax1Date1NetSum2Tax2Date2NetSum3Tax3Date3NetSum4Tax4Date4
1VladP10002.02011-01-011000.22011-01-02nullnullnullnullnullnull
2VoloZ202.02022-01-1320020.02022-02-132000200.02022-03-13nullnullnull
3AlexL400.42012-08-104004.02012-09-10400040.02012-10-10nullnullnull
4JoeB10000010000.02022-10-101000000100000.02023-10-10nullnullnullnullnullnull
0kjbasz6

0kjbasz62#

I don't think you need such a complicated solution like the other answer.

You just need to assign a row-number, then do a manual pivot using MAX(CASE

SELECT
  d.ID,
  d.FirstName,
  d.SurName,
  Net1  = MAX(CASE WHEN d.rn = 1 THEN d.NetSum END),
  Tax1  = MAX(CASE WHEN d.rn = 1 THEN d.Tax    END),
  Date1 = MAX(CASE WHEN d.rn = 1 THEN d.Date   END),
  Net2  = MAX(CASE WHEN d.rn = 2 THEN d.NetSum END),
  Tax2  = MAX(CASE WHEN d.rn = 2 THEN d.Tax    END),
  Date2 = MAX(CASE WHEN d.rn = 2 THEN d.Date   END),
  Net3  = MAX(CASE WHEN d.rn = 3 THEN d.NetSum END),
  Tax3  = MAX(CASE WHEN d.rn = 3 THEN d.Tax    END),
  Date3 = MAX(CASE WHEN d.rn = 3 THEN d.Date   END)
FROM (
    SELECT *,
      rn = ROW_NUMBER() OVER (PARTITION BY d.ID, d.FirstName, d.SurName ORDER BY d.Date)
    FROM Data d
) d
GROUP BY
  d.ID,
  d.FirstName,
  d.SurName;

db<>fiddle

相关问题