[英]mysql pivot/crosstab query
問題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;
至於您的第二個,請說清楚您要做什么。
在您的CASE
子句中添加GROUP_CONCAT
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的解決方案,以解決您的第二個問題。 以下代碼生成您最初請求的格式,其值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
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.