Jeff
Jeff

Reputation: 35

simple SQL Pivot Query

I apologize for my ignorance. I just am not familiar with pivot queries AT ALL and all the examples I find seem about as clear as mud. I have table that returns GroupName and ID Numbers.

For Example:

SELECT GroupName, IDnumber FROM do.Table_1

Returns

GroupName                IDnumber
1                          8395
1                          A660
1                          8396
1                          A661
2                          8398
2                          A662
2                          8399

What I want is something more like this:

GroupName              ID1     ID2   ID3   ID4
1                      8395   A660  8396   A661
2                      8398   A662  8399   NULL

How can I do this? Pivot query? Some other method?

I am open to suggestion and appreciate any help you could provide.

Upvotes: 1

Views: 341

Answers (2)

Sarath Subramanian
Sarath Subramanian

Reputation: 21281

You may need to use dynamic pivoting since the Id will be dynamic. Here is your sample table

SELECT * INTO #TEMP
FROM 
(
SELECT 1 GroupName,                '8395' IDnumber
  UNION ALL
SELECT 1,                          'A660'
  UNION ALL
SELECT 1,                          '8396'
  UNION ALL
SELECT 1,                          'A661'
  UNION ALL
SELECT 2,                          '8398'
  UNION ALL
SELECT 2,                          'A662'
  UNION ALL
SELECT 2,                          '8399'
)TAB

Select row number over each Groupname and insert into a temporary table so that it can be used for both selecting the columns for pivoting and inside the pivot

SELECT *,
'ID' + CAST(ROW_NUMBER() OVER(PARTITION BY GroupName ORDER BY GROUPNAME) AS VARCHAR(10)) IDS
INTO #NEWTABLE
FROM #TEMP

Select columns for pivot

DECLARE @cols NVARCHAR (MAX)

SELECT @cols = COALESCE (@cols + ',[' + IDS + ']', 
           '[' + IDS + ']')
           FROM    (SELECT DISTINCT IDS FROM #NEWTABLE) PV  
           ORDER BY IDS

Now pivot dynamically

DECLARE @query NVARCHAR(MAX)
SET @query = '           
              SELECT * FROM 
             (
                 SELECT * FROM #NEWTABLE
             ) x
             PIVOT 
             (
                 MAX(IDnumber)
                 FOR IDS IN (' + @cols + ')
            ) p      

            '     
EXEC SP_EXECUTESQL @query

Click here to view the result (incase an error is occured on loading page press RUNSQL, it works)

RESULT

enter image description here

Upvotes: 0

Mahmoud Gamal
Mahmoud Gamal

Reputation: 79909

Yes, you can do it using PIVOT but not in this shape, you have firstly to generate a row number to use it to format the data in the way you want. Something like this:

WITH Ranked
AS
(
  SELECT GroupName, IDnumber, 
     ROW_NUMBER() OVER(PARTITION BY GroupName ORDER BY GroupName) AS RN
  FROM Table1
)
SELECT GroupName,
  [1] AS ID1, [2] AS ID2, [3] AS ID3, [4] AS ID4
FROM Ranked AS r
PIVOT
(
  MAX(IDnumber)
  FOR RN IN([1], [2], [3], [4])
) AS p;

This will give you:

| GROUPNAME |  ID1 |  ID2 |  ID3 |    ID4 |
|-----------|------|------|------|--------|
|         1 | 8395 | A660 | 8396 |   A661 |
|         2 | 8398 | A662 | 8399 | (null) |

If you want to do it dynamically and not to write the row number by hand in the pivot table operator, you have to do it using dynamic SQL, something like:

DECLARE @cols AS NVARCHAR(MAX);
DECLARE @colnames AS NVARCHAR(MAX);
DECLARE @query AS NVARCHAR(MAX);

SELECT @cols = STUFF((SELECT distinct ',' +
                        QUOTENAME(RN)
                       FROM 
               (
                 SELECT ROW_NUMBER() OVER(PARTITION BY GroupName ORDER BY GroupName) AS RN
                 FROM Table1 
               ) AS t
                      FOR XML PATH(''), TYPE
                     ).value('.', 'NVARCHAR(MAX)') 
                        , 1, 1, '');

SELECT @colnames = STUFF((SELECT distinct ',' +
                        QUOTENAME(RN) + 'AS' +   
                        QUOTENAME('ID' + CAST(RN AS NVARCHAR(5)))
                       FROM 
               (
                 SELECT ROW_NUMBER() OVER(PARTITION BY GroupName ORDER BY GroupName) AS RN
                 FROM Table1 
               ) AS t
                      FOR XML PATH(''), TYPE
                     ).value('.', 'NVARCHAR(MAX)') 
                        , 1, 1, '');

SELECT @query = 'WITH Ranked
                  AS
                  (
                    SELECT GroupName, IDnumber, 
                    ROW_NUMBER() OVER(PARTITION BY GroupName ORDER BY GroupName) AS RN
                    FROM Table1
                  )
                  SELECT GroupName, ' + @colnames +
                  ' FROM Ranked AS r
                  PIVOT
                  (
                    MAX(IDnumber)
                    FOR RN IN(' + @cols + ')' +
                  ') p';

execute(@query);

This should give you the same result:

| GROUPNAME |  ID1 |  ID2 |  ID3 |    ID4 |
|-----------|------|------|------|--------|
|         1 | 8395 | A660 | 8396 |   A661 |
|         2 | 8398 | A662 | 8399 | (null) |

Upvotes: 3

Related Questions