13

質問 1:以下の構造とデータを持つテーブルがあります。

app_id  transaction_id  mobile_no   node_id  customer_attribute  entered_value 
100     111             9999999999  1        Q1                  2                             
100     111             9999999999  2        Q2                  1                             
100     111             9999999999  3        Q3                  4                             
100     111             9999999999  4        Q4                  3                             
100     111             9999999999  5        Q5                  2                             
100     222             8888888888  4        Q4                  1                             
100     222             8888888888  3        Q3                  2                             
100     222             8888888888  2        Q2                  1                             
100     222             8888888888  1        Q1                  3                             
100     222             8888888888  5        Q5                  4                             

これらのレコードを以下の形式で表示したい:

app_id  |  transaction_id  | mobile     |  Q1  |  Q2  |  Q3  |  Q4 |  Q5  |
 100    |      111         | 9999999999 |   2  |   1  |   4  |  3  |  2   |
 100    |      222         | 8888888888 |   3  |   1  |   2  |  1  |  4   |

この表示を取得するには、クロス集計/ピボット クエリを使用する必要があることを知っています。このために、私はそれについて持っている限られた知識に基づいて試しました. 以下は私の質問です:

SELECT app_id, transaction_id, mobile_no,
  (CASE node_id WHEN 1 THEN entered_value ELSE '' END) AS user_input1,
  (CASE node_id WHEN 2 THEN entered_value ELSE '' END) AS user_input2,
  (CASE node_id WHEN 3 THEN entered_value ELSE '' END) AS user_input3,
  (CASE node_id WHEN 4 THEN entered_value ELSE '' END) AS user_input4,
  (CASE node_id WHEN 5 THEN entered_value ELSE '' END) AS user_input5
FROM trn_user_log 
GROUP BY app_id, transaction_id, mobile_no, node_id

そして、このクエリに基づいて、以下の表示を得ました。

app_id  transaction_id  mobile_no   user_input1  user_input2  user_input3  user_input4  user_input5  
100     111             9999999999  2                                                                
100     111             9999999999               1                                                   
100     111             9999999999                            4                                      
100     111             9999999999                                         3                         
100     111             9999999999                                                      2            
100     222             8888888888  3                                                                
100     222             8888888888               1                                                   
100     222             8888888888                            2                                      
100     222             8888888888                                         1                         
100     222             8888888888                                                      4            

上記のように複数の行ではなく、単一の行でレコードを取得するためにクエリに加える必要がある適切な変更を誰でも手伝ってもらえますか。

質問 2:また、特定のフィールドの値を列の名前として取得する方法はありますか。上記のように、ヘッダーとしてuser_input1, ,... があります。その代わりに、列のヘッダーとしてuser_input2値を入れたいと思っています。customer_attribute

このために、私NAME_CONST(name,value)は以下のようにチェックしました:

SELECT app_id, transaction_id, mobile_no,
NAME_CONST(customer_attribute, (CASE node_id WHEN 1 THEN entered_value ELSE '' END))
FROM trn_user_log 

しかし、それはエラーを与えます

Error Code : 1210 Incorrect arguments to NAME_CONST

ヘルプが必要です。

4

3 に答える 3

20

@Johnの静的な回答はうまく機能しますが、変換したい列の数が不明な場合は、準備されたステートメントを使用して結果を取得することを検討します。

SET @sql = NULL;
SELECT
  GROUP_CONCAT(DISTINCT
    CONCAT(
      'GROUP_CONCAT((CASE node_id when ',
      node_id,
      ' then entered_value else NULL END)) AS user_input',
      node_id
    )
  ) INTO @sql
FROM trn_user_log;


SET @sql = CONCAT('SELECT app_id, transaction_id, mobile_no, ', @sql, ' 
                  FROM trn_user_log 
                  GROUP BY app_id, transaction_id, mobile_no');

PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

SQL Fiddle with Demoを参照してください

あなたの2番目に関しては、あなたがやろうとしていることを明確にしてください。それは明確ではありません.

于 2012-09-12T10:27:09.473 に答える
8

GROUP_CONCATあなたのCASE句に追加してください

SELECT app_id, transaction_id, mobile_no,
  GROUP_CONCAT((CASE node_id WHEN 1 THEN entered_value ELSE NULL END)) AS user_input1,
  GROUP_CONCAT((CASE node_id WHEN 2 THEN entered_value ELSE NULL END)) AS user_input2,
  GROUP_CONCAT((CASE node_id WHEN 3 THEN entered_value ELSE NULL END)) AS user_input3,
  GROUP_CONCAT((CASE node_id WHEN 4 THEN entered_value ELSE NULL END)) AS user_input4,
  GROUP_CONCAT((CASE node_id WHEN 5 THEN entered_value ELSE NULL END)) AS user_input5
FROM trn_user_log 
GROUP BY app_id, transaction_id, mobile_no

SQLFiddle デモ

于 2012-09-12T07:05:28.287 に答える
2

@DarkKnightFan、これは私が取り組んでいたタスクにとって非常に役立つ質問でした。先に進み、@bluefin のソリューションを修正して、2 番目の質問を解決しました。次のコードは、最初に要求された形式を作成し、customer_attribute の値をクロス集計の結果の列見出しとして使用します。

関連する変更は次のとおりです。

' then entered_value else NULL END)) AS user_input',
      node_id

これに:

' then entered_value else NULL END)) AS ''',
          customer_attribute,''''

完全なコード:

SET @sql = NULL;
SELECT
  GROUP_CONCAT(DISTINCT
    CONCAT(
      'GROUP_CONCAT((CASE node_id when ',
      node_id,
      ' then entered_value else NULL END)) AS ''',
      customer_attribute,''''
    )
  ) INTO @sql
FROM trn_user_log;


SET @sql = CONCAT('SELECT app_id, transaction_id, mobile_no, ', @sql, ' 
                  FROM trn_user_log 
                  GROUP BY app_id, transaction_id, mobile_no');

PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

また、この問題を参照している他のユーザーの場合、クロス集計しようとしている値が多数ある場合、GROUP_CONCAT() のデフォルトの最大長は 1024 文字であるため、エラーが発生する可能性があります。増やすには、これを準備済みステートメントの先頭に置きます。

SET SESSION group_concat_max_len = value; -- replace value with an int
于 2014-01-12T18:03:37.583 に答える