具有动态数据透视的Mysql查询

具有动态数据透视的Mysql查询,mysql,sql,pivot-table,Mysql,Sql,Pivot Table,我有一个表名为grades,如下所示: +--------+--------+-----------+ | userid | itemid | finalgrade| +--------+--------+-----------+ | 1 | 7 | 100 | | 1 | 8 | 89 | | 2 | 7 | 87 | | 2 | 8

我有一个表名为grades,如下所示:

  +--------+--------+-----------+
  | userid | itemid | finalgrade|
  +--------+--------+-----------+
  |  1     |   7    |    100    | 
  |  1     |   8    |    89     |    
  |  2     |   7    |    87     |     
  |  2     |   8    |    17     |    
  |  3     |   7    |    87     |   
  |  3     |   8    |    38     |   
  +--------+--------+-----------+
  +--------+---+---+
  | userid | 7 | 8 |
  +--------+---+---+
  |  1     |100| 89| 
  |  2     |87 | 17|        
  |  3     |87 | 38|    
  +--------+---+---+
SELECT userid,
  MAX(CASE WHEN itemid=7 THEN finalgrade END) as c7,
  MAX(CASE WHEN itemid=8 THEN finalgrade END) as c8,
FROM grades
GROUP BY userid
SELECT    
  CONCAT(    
    'SELECT userid,',    
    GROUP_CONCAT(CONCAT('MAX(CASE WHEN itemid=', itemid, ' THEN finalgrade END) AS c', itemid)),    
    ' FROM tablename GROUP BY userid')    
FROM (SELECT DISTINCT itemid FROM tablename) s INTO @sql;

PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
我想创建一个pivot查询,将表更改为:

  +--------+--------+-----------+
  | userid | itemid | finalgrade|
  +--------+--------+-----------+
  |  1     |   7    |    100    | 
  |  1     |   8    |    89     |    
  |  2     |   7    |    87     |     
  |  2     |   8    |    17     |    
  |  3     |   7    |    87     |   
  |  3     |   8    |    38     |   
  +--------+--------+-----------+
  +--------+---+---+
  | userid | 7 | 8 |
  +--------+---+---+
  |  1     |100| 89| 
  |  2     |87 | 17|        
  |  3     |87 | 38|    
  +--------+---+---+
SELECT userid,
  MAX(CASE WHEN itemid=7 THEN finalgrade END) as c7,
  MAX(CASE WHEN itemid=8 THEN finalgrade END) as c8,
FROM grades
GROUP BY userid
SELECT    
  CONCAT(    
    'SELECT userid,',    
    GROUP_CONCAT(CONCAT('MAX(CASE WHEN itemid=', itemid, ' THEN finalgrade END) AS c', itemid)),    
    ' FROM tablename GROUP BY userid')    
FROM (SELECT DISTINCT itemid FROM tablename) s INTO @sql;

PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
我有一个解决方案,使用如下定义的itemid:

select *,
truncate (sum(finalgrade*(1-abs(sign(itemid-7)))),0) as 7,
truncate (sum(finalgrade*(1-abs(sign(itemid-8)))),0) as 8,
FROM grades
group by userid"

问题是,我需要相同的查询,但没有定义itemid,动态创建列。

我想您需要这样的查询:

  +--------+--------+-----------+
  | userid | itemid | finalgrade|
  +--------+--------+-----------+
  |  1     |   7    |    100    | 
  |  1     |   8    |    89     |    
  |  2     |   7    |    87     |     
  |  2     |   8    |    17     |    
  |  3     |   7    |    87     |   
  |  3     |   8    |    38     |   
  +--------+--------+-----------+
  +--------+---+---+
  | userid | 7 | 8 |
  +--------+---+---+
  |  1     |100| 89| 
  |  2     |87 | 17|        
  |  3     |87 | 38|    
  +--------+---+---+
SELECT userid,
  MAX(CASE WHEN itemid=7 THEN finalgrade END) as c7,
  MAX(CASE WHEN itemid=8 THEN finalgrade END) as c8,
FROM grades
GROUP BY userid
SELECT    
  CONCAT(    
    'SELECT userid,',    
    GROUP_CONCAT(CONCAT('MAX(CASE WHEN itemid=', itemid, ' THEN finalgrade END) AS c', itemid)),    
    ' FROM tablename GROUP BY userid')    
FROM (SELECT DISTINCT itemid FROM tablename) s INTO @sql;

PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
但您希望它具有动态值,然后可以使用这样一个准备好的语句:

  +--------+--------+-----------+
  | userid | itemid | finalgrade|
  +--------+--------+-----------+
  |  1     |   7    |    100    | 
  |  1     |   8    |    89     |    
  |  2     |   7    |    87     |     
  |  2     |   8    |    17     |    
  |  3     |   7    |    87     |   
  |  3     |   8    |    38     |   
  +--------+--------+-----------+
  +--------+---+---+
  | userid | 7 | 8 |
  +--------+---+---+
  |  1     |100| 89| 
  |  2     |87 | 17|        
  |  3     |87 | 38|    
  +--------+---+---+
SELECT userid,
  MAX(CASE WHEN itemid=7 THEN finalgrade END) as c7,
  MAX(CASE WHEN itemid=8 THEN finalgrade END) as c8,
FROM grades
GROUP BY userid
SELECT    
  CONCAT(    
    'SELECT userid,',    
    GROUP_CONCAT(CONCAT('MAX(CASE WHEN itemid=', itemid, ' THEN finalgrade END) AS c', itemid)),    
    ' FROM tablename GROUP BY userid')    
FROM (SELECT DISTINCT itemid FROM tablename) s INTO @sql;

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

您可以使用SUM而不是MAX,这取决于数据的结构。

谢谢您的解决方案,但查询有语法错误:
您的SQL语法有错误;查看与您的MySQL服务器版本对应的手册,了解使用near“PREPARE stmt FROM@sql;执行stmt;在第8行取消分配PREPARE stmt。
@EnriqueBerrueta对我来说是正确的:itemid是INT列吗?是的,itemid是INT。我使用的是SqlFIDLE,这让我很惊讶,因为它是正确的,问题是当我在phpmyadmin或php中使用它时。@EnriqueBerrueta您有很多不同的itemid吗?group_concat有一个长度限制,我怀疑查询可能已被剪切。。。但是可以使用
set group_concat_max_len=”修改此限制默认值为1024,您可以尝试使用10000…是的,这对我有一点帮助,但现在查询给了我另一个错误:
Unknown prepared statement handler(stmt)given to EXECUTE