Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
174 views
in Technique[技术] by (71.8m points)

mysql - Transposing groups of rows with the same ID into another table

I have a table, Demo1, where I have multiple similar DIM_KEY's for several different ATTR_NAME's (attribute names). I want to display a table with columns for DIM_KEY, UPC, DAIRY_CLM, KOSHER_CLM, FAT, and CALORIES where the matching values are the rows.

This is the original table Demo1: [1]: https://imgur.com/a/KqayM1C



This is what I want it to look like (table: Demo2): [2]: https://imgur.com/a/nwpoHhv

I've tried inserting the rows from Demo1 into an empty Demo2 table but that didn't work out like I wanted it to. I also couldn't get the DIM_KEY in that way. I also tried using PIVOT but got nothing but errors. I am using MySQL but this also needs to work in SSMS. Preferibly SSMS if I had to choose one.

INSERT INTO Demo2 (UPC, DAIRY_CLM, KOSHER_CLM, FAT, CALORIES)
SELECT
    (CASE WHEN ATTR_NAME = 'UPC' THEN VALUE END),
    (CASE WHEN ATTR_NAME = 'DAIRY_CLM' THEN VALUE END),
    (CASE WHEN ATTR_NAME = 'KOSHER_CLM' THEN VALUE END),
    (CASE WHEN ATTR_NAME = 'FAT' THEN VALUE END),
    (CASE WHEN ATTR_NAME = 'CALORIES' THEN VALUE END)
FROM Demo1;
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

This is indeed a pivot, also called a crosstab, or sometimes transpose

Some databases have dedicated facilities for doing it, others you have to use a grouping syntax. I prefer the latter because it works universally

If it's any consolation, you were really close!

SELECT
    DIM_KEY,
    MAX(CASE WHEN ATTR_NAME = 'UPC' THEN VALUE END) as UPC,
    MAX(CASE WHEN ATTR_NAME = 'DAIRY_CLM' THEN VALUE END) as DAIRY_CLM,
    MAX(CASE WHEN ATTR_NAME = 'KOSHER_CLM' THEN VALUE END) as KOSHER_CLM,
    MAX(CASE WHEN ATTR_NAME = 'FAT' THEN VALUE END) as FAT,
    MAX(CASE WHEN ATTR_NAME = 'CALORIES' THEN VALUE END) as CALORIES
FROM demo
GROUP BY DIM_KEY

How does it work?

Well, if you run the non-grouped, no-max-functions version that you already had:

SELECT
    DIM_KEY,
    (CASE WHEN ATTR_NAME = 'UPC' THEN VALUE END),
    (CASE WHEN ATTR_NAME = 'DAIRY_CLM' THEN VALUE END),
    (CASE WHEN ATTR_NAME = 'KOSHER_CLM' THEN VALUE END),
    (CASE WHEN ATTR_NAME = 'FAT' THEN VALUE END),
    (CASE WHEN ATTR_NAME = 'CALORIES' THEN VALUE END)
FROM
   demo

Then you'll see your data become "diagonal":

3005, 123423, null, null...
3005, null,   N,    null...
3005, null,   null, Y   ...

In each column (per dim_key) there is only one value, the rest are NULL

Adding in the GROUP BY and MAX causes these to collapse into a single row because MAX() will return just the value from the column and make all the nulls disappear. It's an intrinsic property of a grouping, that the row data doesnt "stay together" - within the group of a particular DIM_KEY, the MAX(DAIRY_CLM) can come from any row, the MAX(KOSHER_CLM) can come from any other row.. In practice this means that the single values are picked, the nulls are discarded, they all appear on the same row..

..and thus your vertical data went horizontal, after going through the diagonal


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...