2012-09-12 42 views
6

問題1:我與下面的結構和數據的表格:MySQL的樞軸/交叉表查詢

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_input1user_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 

幫助。

回答

16

雖然@約翰的靜態回答的偉大工程,如果你有一個未知的數字,要轉換列,我會考慮使用預處理語句得到的結果:

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

至於你的第二,請澄清你正在嘗試做什麼,目前尚不清楚。

+0

男人!!你閱讀我的想法......這正是我想要的,我正在做..我正在寫一個存儲過程來做同樣的事情。非常感謝!!! – DarkKnightFan

+0

@Gaurav沒問題,但我沒有完全理解你的第二個問題。 – Taryn

+0

是的,這非常棘手..我懷疑這甚至可能寫入SQL。我想將一個名爲'customer_attr'的列的值作爲頭部代替'user_input'。因此,例如'Q1'應該顯示在'user_input1'的位置。我知道我可以通過單獨獲取標題列並同樣顯示它來處理java代碼中的這件事。但我只是想知道這樣的事情是否可能。無論如何感謝您的幫助。 – DarkKnightFan

7

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 

SQLFiddle Demo

+0

對不起,但它沒有工作! – DarkKnightFan

+0

@Gaurav爲什麼在[SQLFiddle](http://sqlfiddle.com/#!2/7cbde/4)中工作?刪除您的羣組中的'node_id'條款 –

+0

非常好!它現在工作。忘了從groupby中刪除'node_id'。你對我的第二個問題有答案嗎?顯示'customer_attribute'的值代替'user_inputx'? – DarkKnightFan

1

@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