Home > Software engineering >  Pivot column to rows in SQL
Pivot column to rows in SQL

Time:02-24

Looking for any solution to convert columns to rows.

I have my columns as [CA_resp],[CA_spen],[TX_resp],[TX_spen],[PA_resp],[PA_spen],these columns need to be converted to rows. all the states (CA,TX,PA) should go into [market] column,[resp] need to be other column [spen] need to be other column.

Here is an example: I have a table with the following schema:

 CREATE TABLE stage.test(
         id int null,
        [month] [varchar](255) NULL, 
        [year] [float] NULL,
        CA_resp [float] NULL,
        CA_spen [money] NULL,
        TX_resp [float] NULL, 
        TX_spen [money] NULL,
        PA_resp [float] NULL,   
        PA_spen [money] NULL)
    
    INSERT into stage.test
    values(1,    'jan', 2022,222,`enter code here`450,111,450,444,550)
    

I want my output to be.

    ID, month,year, market, resp ,spen
    1    jan    2022    CA  222     350
    1    jan    2022    TX  111     450
    1    jan    2022    PA  444     550

I tried using Pivot and didn't work.

CodePudding user response:

You can simply use 3 queries with UNION ALL. This approach is very efficient because we output 3 simple queries one after the other. There is no join or other comparison of data. (A join with UNION without all is a different story because it compares the queries to eliminate duplicates.)

     CREATE TABLE stagetest(
              id int null,
             [month] [varchar](255) NULL, 
             [year] [float] NULL,
             CA_resp [float] NULL,
             CA_spen [money] NULL,
             TX_resp [float] NULL, 
             TX_spen [money] NULL,
             PA_resp [float] NULL,   
             PA_spen [money] NULL);
         
         INSERT into stagetest
         values(1,    'jan', 2022,222,450,111,450,444,550);
     --ID, month,year, market, resp ,spen
      --   1    jan    2022    CA  222     350
     --    1    jan    2022    TX  111     450
     --    1    jan    2022    PA  444
     SELECT id, [month], [year], 'CA' market, ca_resp Resp, ca_spen Spen
     from stagetest
     union all
     SELECT id, [month], [year], 'PA', pa_resp, pa_spen
     from stagetest
     union all
     SELECT id, [month], [year], 'TX', tx_resp, tx_spen
     from stagetest;
id month year market Resp Spen
1 jan 2022 CA 222 450.0000
1 jan 2022 PA 444 550.0000
1 jan 2022 TX 111 450.0000

fiddle here

CodePudding user response:

You cannot use Pivot in your case, since you don't have enough rows/columns.
You need to "create" rows, which can be done using seperate select statements combined with union.
I prefer to cross join them so you don't have to repeat the same columns in every select.
But you can also use the select with union direct, it's up to you

select t.id, t.month, t.year, v.market, v.CA_resp as resp, v.CA_spen as spen
from   test t
  cross join (select 'CA' as market, CA_resp, CA_spen from test
              union
              select 'TX' as market, TX_resp, TX_spen from test
              union
              select 'PA' as market, PA_resp, PA_spen from test
             ) v

The result is

id month year market resp spen
1 jan 2022 CA 222 450.0000
1 jan 2022 PA 444 550.0000
1 jan 2022 TX 111 450.0000

Here is the DBFiddle

Or you could just put all fields in 3 selects with union, the result is the same just use what you like best

select id, month, year, 'CA' as market, CA_resp as resp, CA_spen as spen from test
union
select id, month, year, 'TX' as market, TX_resp, TX_spen from test
union
select id, month, year, 'PA' as market, PA_resp, PA_spen from test
  • Related