SQL turning rows into columns and populating with values

一世执手 提交于 2021-02-19 08:22:08

问题


I'm not quite sure why this table was designed this way, but it's making it hard to solve my problem. Looking at the data:

NAME            TYPE_NAME               DEFAULT_VALUE           VALUE
TEST 1          Currency                Null                    14
TEST 1          Event Count             0                       0
TEST 1          Usage                   8                       Null
TEST 1          Events Amt              0                       0
TEST 1          Usage Amt               Null                    13
TEST 1          From Date               Null                    5
TEST 1          To Date                 6                       Null
TEST 1          Traffic Scenario        Null                    2
TEST 1          Band                    1                       Null
TEST 1          Service                 15                      Null
TEST 1          Tariff Rate Name        Null                    4
TEST 2          Currency                EUR                     0
TEST 2          Event Count             Null                    9
TEST 2          Usage                   10                      Null
TEST 2          Events Amt              Null                    13
TEST 2          Usage Amt               Null                    14
TEST 2          From Date               Null                    3
TEST 2          To Date                 4                       Null
TEST 2          Traffic Scenario        Null                    5
TEST 2          Band                    6                       Null
TEST 2          Service                 7                       Null
TEST 2          Tariff Rate Name        Null                    8
TEST 3          Currency                USD                     0
TEST 3          Event Count             0                       0
TEST 3          Usage                   4                       Null
TEST 3          Events Amt              0                       0
TEST 3          Usage Amt               Null                    5
TEST 3          From Date               Null                    1
TEST 3          To Date                 2                       Null
TEST 3          Traffic Scenario        13603                   0
TEST 3          Band                    3                       Null
TEST 3          Service                 3                       Null
TEST 3          Tariff Rate Name        24HR                    0

What I need help with is to do the following: For each name have the type_name as a column and then fill those columns with the default_value or value.

Like this:

NAME    Currency        Event Count     Usage   Events Amt      Usage Amt       From Date       To Date Traffic Scenario        Band    Service Tariff Rate Name
TEST 1  14              0               8       0               13              5               6       2                       1       15      4
TEST 2  EUR             9               10      13              14              3               4       5                       6       7       8
TEST 3  USD             0               4       0               5               1               2       13603                   3       3       24HR

Basically populates from default_value or value depending which one is not null, if both zero then just 0.

Could anyone help me with this as my SQL knowledge is lacking here.

Many thanks!


回答1:


You can use PIVOT as follows:

SELECT * FROM
( SELECT NAME, TYPE_NAME, COALESCE(VALUE, DEFAULT_VALUE) AS VAL
    FROM YOUR_TABLE
) 
PIVOT 
( MAX ( VAL )
  FOR TYPE_NAME IN ( 'Currency' AS CURRENCY, 'Event Count' AS EVENT_COUNT, 
                       'Usage' AS USAGE_, 'Events Amt' AS EVENTS_AMT )
)

Cheers!!




回答2:


This is an EAV (entity-attribute-value) table. If you know the columns you want, you can use conditional aggregation:

select name,
       max(case when type_name = 'Currency' then default_value end) as currency,
       max(case when type_name = 'Event Count ' then default_value end) as EventCount,
       . . . 
from t
group by name;

If you don't know all the types, then you need dynamic SQL -- that is, PL/SQL in Oracle.




回答3:


You can do conditional aggregation:

select 
    name,
    max(case when type_name = 'Currency'
        then coalesce(value, default_value)
    end) currency,
    max(case when type_name = 'Event Count' 
        then coalesce(value, default_value) 
    end) event_count,
    max(case when type_name = 'Usage'
        then coalesce(value, default_value)
    end ) usage,
    max(case when type_name = 'Events Amt'
        then coalesce(value, default_value)
    end) events_amt
from mytable
group by name

The conditional expressions actually pivots the resulset; coalesce() returns either value, if it is not null, or default_value.




回答4:


You can try it. I tried on oracle.

Also this method COALESCE (DEFAULT_VALUE, VALUE) needs to control first DEFAULT_VALUE and second VALUE.

SELECT t1.NAME,
max(CASE WHEN t1.TYPE_NAME ='Currency'      THEN COALESCE (t1.DEFAULT_VALUE, T1.VALUE) END) AS Currency,
max(CASE WHEN t1.TYPE_NAME ='Event Count'   THEN COALESCE (t1.DEFAULT_VALUE, T1.VALUE) END) AS Event_Count
max(CASE WHEN t1.TYPE_NAME ='Usage'         THEN COALESCE (t1.DEFAULT_VALUE, T1.VALUE) END) AS Usage,
max(CASE WHEN t1.TYPE_NAME ='Usage Amt'     THEN COALESCE (t1.DEFAULT_VALUE, T1.VALUE) END) AS Usage_Amt,
max(CASE WHEN t1.TYPE_NAME ='From Date'     THEN COALESCE (t1.DEFAULT_VALUE, T1.VALUE) END) AS From_Date,
max(CASE WHEN t1.TYPE_NAME ='Band'          THEN COALESCE (t1.DEFAULT_VALUE, T1.VALUE) END) AS Band,
.......
......
FROM MYTABLE t1 GROUP BY t1.NAME


来源:https://stackoverflow.com/questions/60670251/sql-turning-rows-into-columns-and-populating-with-values

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!