Mysql, reshape data from long / tall to wide

前端 未结 3 763
Happy的楠姐
Happy的楠姐 2020-12-02 23:26

I have data in a mysql table in long / tall format (described below) and want to convert it to wide format. Can I do this using just sql?

Easiest to explain with an

相关标签:
3条回答
  • 2020-12-02 23:52

    If you were using SQL Server, this would be easy using UNPIVOT. As far as I am aware, this is not implemented in MySQL, so if you want to do this (and I'd advise against it) you'll probably have to generate the SQL dynamically, and that's messy.

    0 讨论(0)
  • 2020-12-02 23:54

    Cross-tabs or pivot tables is the answer. From there you can SELECT FROM ... INSERT INTO ... or create a VIEW from the single SELECT.

    Something like:

    SELECT country, 
           MAX( IF( key='President', value, NULL ) ) AS President,
           MAX( IF( key='Currency', value, NULL ) ) AS Currency,
           ...
    
    FROM table 
    GROUP BY country;
    

    For more info: http://dev.mysql.com/tech-resources/articles/wizard/index.html

    0 讨论(0)
  • 2020-12-02 23:55

    I think I found the solution, which uses VIEWS and INSERT INTO (as suggested by e4c5).

    You have to get your list of AttrNames/Keys yourself, but MYSQL does the other heavy lifting.

    For the simple test case above, create the new_table with the appropriate columns (don't forget to have an auto-increment primary key as well). Then

    CREATE VIEW a
    AS SELECT country, attrValue
    WHERE attrName="President";
    
    CREATE VIEW b
    AS SELECT country, attrValue
    WHERE attrName="Currency";
    
    
    INSERT INTO newtable(country, President, Currency)
    SELECT a.country, a.attrValue, b.attrValue
    FROM  a
    INNER JOIN b  ON a.country=b.country;
    

    If you have more attrNames, then create one view for each one and then adjust the last statement accordingly.

    INSERT INTO newtable(country, President, Currency, Capital, Population)
    SELECT a.country, a.attrValue, b.attrValue, c.attrValue, d.attrValue
    FROM  a
    INNER JOIN b  ON a.country=b.country
    INNER JOIN c  ON a.country=c.country
    INNER JOIN d  ON a.country=d.country;
    

    Some more tips

    • use NATURAL LEFT JOIN and you don't have to specify the ON clause
    0 讨论(0)
提交回复
热议问题