2012-09-12 44 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