web-dev-qa-db-ja.com

MySQLピボットクエリで列を合計でソートできない

国が他の国から輸入する正味重量を表す行列の結果を返そうとしています。

Mysqlでピボットタイプのテーブルを生成するクエリを作成することができました。すべてのデータは単一のテーブルから取得されます。列(輸出国)を動的に作成し、その国で輸入された総正味重量で行を並べ替えることができました。

私が元に戻ろうとしているのは、列である輸出国を分類することです。簡単にアルファベット順に並べ替えることができますが、その列を動的に生成し、その列の合計で並べ替えるときに、何らかの方法で各列を合計する必要があります。

これは、myクエリの前のテーブルの例です。

REPORTER | PARTNER | NET_WEIGHT | YEAR | COMMODITY
--------------------------------------------------
Spain    | USA     | 3          | 2010 | wheat
Mexico   | France  | 5          | 2011 | wheat
Norway   | USA     | 2          | 2012 | wheat
Egypt    | Canada  | 5          | 2010 | wheat
Germany  | UK      | 1          | 2011 | wheat
Peru     | France  | 3          | 2011 | wheat

これが私が目指している構造の一例です。

REPORTER  | TOTAL  | USA   | France  | Canada  | UK    
------------------------------------------------------
TOTAL     |        | 5     | 4       | 3       | 3           
------------------------------------------------------
Spain     | 9      | 3     | 4       | 2       | NULL
Egypt     | 6      | 2     | NULL    | 1       | 3
Germany   | 3      | 1     | NULL    | NULL    | NULL

これは私がこれまでに作成したクエリですが、上記のテーブルに似ていますが、正しくソートされていません。

SET @@group_concat_max_len = 500000;
SET @sql = NULL;

SELECT GROUP_CONCAT(DISTINCT CONCAT('GROUP_CONCAT(IF(`Partner` = ''', `Partner`,''', `NetWeight`, NULL)) AS ''',`Partner`,'''') 
ORDER BY `Partner` ASC)
INTO @sql FROM `tblAnnualData`;

SET @sql = CONCAT('SELECT `Reporter`,SUM(`NetWeight`) AS Total,', @sql,' FROM `tblAnnualData` 
                    WHERE `Commodity` = ''wheat'' 
                    AND `Year` = 2013 
                    GROUP BY `Reporter`
                    ORDER BY `Total` DESC');

ステートメントでわかるように、「Partner」でアルファベット順に列を並べ替えることができますが、達成したいことは、net_weight列の合計を降順に並べ替えることです。したがって、テーブルを右および下に移動すると、最高値が左上に向かって減少します。

これはできますか? WITH ROLLUPを使用した例を見てきましたが、何も動作しないようです。

3
Matt Fricker

私はあなたの例を編集し、WITH ROLLUPCASE、およびFIELDステートメントを使用して、これをソートおよび作成しました。

情報:

mysql> SELECT * FROM test.tblAnnualData;
+----------+---------+------------+------+-----------+
| REPORTER | PARTNER | NET_WEIGHT | YEAR | COMMODITY |
+----------+---------+------------+------+-----------+
| Egypt    | Canada  |          5 | 2010 | wheat     |
| Germany  | UK      |          1 | 2011 | wheat     |
| Mexico   | France  |          5 | 2011 | wheat     |
| Norway   | USA     |          2 | 2012 | wheat     |
| Peru     | France  |          3 | 2011 | wheat     |
| Spain    | USA     |          3 | 2010 | wheat     |
+----------+---------+------------+------+-----------+
6 rows in set (0.00 sec)

動的クエリ:

SET @@group_concat_max_len = 500000;
SET @QUERY1 = NULL;

SELECT GROUP_CONCAT(DISTINCT CONCAT(" SUM(CASE WHEN PARTNER = '",PARTNER,"' THEN NET_WEIGHT ELSE 0 END) AS '",PARTNER,"'") 
ORDER BY PARTNER ASC)
INTO @QUERY1 
FROM tblAnnualData;

SET @QUERY1 = CONCAT("SELECT
                        REPORTER,
                        TOTAL,
                        USA,
                        France,
                        Canada,
                        UK
                    FROM (SELECT 
                            IFNULL(REPORTER,'TOTAL') AS REPORTER,
                            SUM(NET_WEIGHT) AS TOTAL,",@QUERY1," FROM tblAnnualData 
                    WHERE COMMODITY = 'wheat'
                    #AND Year = 2011
                    GROUP BY REPORTER WITH ROLLUP) AS A
                    ORDER BY FIELD(REPORTER,'TOTAL') DESC,
                        TOTAL DESC,
                        REPORTER ASC;");
PREPARE QUERY1 FROM @QUERY1;
EXECUTE QUERY1;

これは次のクエリと同じです。

SELECT
    REPORTER,
    TOTAL,
    USA,
    France,
    Canada,
    UK
FROM (SELECT 
        IFNULL(REPORTER,'TOTAL') AS REPORTER,
        SUM(NET_WEIGHT) AS TOTAL,
        SUM(CASE WHEN PARTNER='USA' THEN NET_WEIGHT ELSE 0 END) AS USA,
        SUM(CASE WHEN PARTNER='France' THEN NET_WEIGHT ELSE 0 END) AS France,
        SUM(CASE WHEN PARTNER='Canada' THEN NET_WEIGHT ELSE 0 END) AS Canada,
        SUM(CASE WHEN PARTNER='UK' THEN NET_WEIGHT ELSE 0 END) AS UK
    FROM tblAnnualData
    GROUP BY REPORTER WITH ROLLUP) AS A
ORDER BY FIELD(REPORTER,'TOTAL') DESC,
    TOTAL DESC,
    REPORTER ASC;

FIELDなのはなぜですか?

フィールドがFIELDのときに最初にTOTALを使用して並べ替えました(つまり、WITH ROLLUPによって生成された行のREPORTER集計フィールド)。次に、 NET_WEIGHTTOTAL。その後、いくつかのREPORTERが他/他のREPORTERと同じである場合に備えて、TOTALで終了します。

動的クエリのテスト:

mysql> SET @@group_concat_max_len = 500000;
Query OK, 0 rows affected (0.00 sec)

mysql> SET @QUERY1 = NULL;
Query OK, 0 rows affected (0.00 sec)

mysql> 
mysql> SELECT GROUP_CONCAT(DISTINCT CONCAT(" SUM(CASE WHEN PARTNER = '",PARTNER,"' THEN NET_WEIGHT ELSE 0 END) AS '",PARTNER,"'") 
    -> ORDER BY PARTNER ASC)
    -> INTO @QUERY1 
    -> FROM tblAnnualData;
Query OK, 1 row affected (0.00 sec)

mysql> 
mysql> SET @QUERY1 = CONCAT("SELECT
    "> REPORTER,
    "> TOTAL,
    "> USA,
    "> France,
    "> Canada,
    "> UK
    "> FROM (SELECT 
    "> IFNULL(REPORTER,'TOTAL') AS REPORTER,
    "> SUM(NET_WEIGHT) AS TOTAL,",@QUERY1," FROM tblAnnualData 
    "> WHERE COMMODITY = 'wheat'
    "> #AND Year = 2011
    "> GROUP BY REPORTER WITH ROLLUP) AS A
    "> ORDER BY FIELD(REPORTER,'TOTAL') DESC,
    "> TOTAL DESC,
    "> REPORTER ASC;");
Query OK, 0 rows affected (0.00 sec)

mysql> PREPARE QUERY1 FROM @QUERY1;
Query OK, 0 rows affected, 1 warning (0.00 sec)
Statement prepared

mysql> EXECUTE QUERY1;
+----------+-------+------+--------+--------+------+
| REPORTER | TOTAL | USA  | France | Canada | UK   |
+----------+-------+------+--------+--------+------+
| TOTAL    |    19 |    5 |      8 |      5 |    1 |
| Egypt    |     5 |    0 |      0 |      5 |    0 |
| Mexico   |     5 |    0 |      5 |      0 |    0 |
| Peru     |     3 |    0 |      3 |      0 |    0 |
| Spain    |     3 |    3 |      0 |      0 |    0 |
| Norway   |     2 |    2 |      0 |      0 |    0 |
| Germany  |     1 |    0 |      0 |      0 |    1 |
+----------+-------+------+--------+--------+------+
7 rows in set, 1 warning (0.00 sec)

mysql> 

SQLFiddle で試してください

2
oNare