質問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
_
ヘルプが必要です。
@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番目に関しては、あなたが何をしようとしているのか明確にしないでください。
追加 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
@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