【问题标题】:how to use MySQL for a dynamic pivot table or crosstab如何将 MySQL 用于动态数据透视表或交叉表
【发布时间】:2012-12-23 08:56:52
【问题描述】:

我知道这个问题或其变体已被问过多次,我什至尝试过实施解决方案,但我正在努力完成它。

我有一个非常简单的表,其中包含三个数据列:Date1、Report_#、Name。我想将它围绕日期和各种名称作为标题选项卡进行旋转,并让所有报告编号出现在下面。

所以它看起来像这样:

Report | Date   | Name                     Date   | Name1 | Name2 | Name3
-----------------------                    ------------------------------
1      | 4-5-12 | Name1                    4-5-12 | 1     | 2     | 3
2      | 4-5-12 | Name2      ----->        4-6-12 | 4     | 5     | 6
3      | 4-5-12 | Name3                    4-7-12 | 7     | 8     | 9
4      | 4-6-12 | Name1                    
5      | 4-6-12 | Name2                    
6      | 4-6-12 | Name3                    
7      | 4-7-12 | Name1
8      | 4-7-12 | Name2
9      | 4-7-12 | Name3

我能够从http://www.artfulsoftware.com/infotree/queries.php#78 知道该怎么做,但我被困住了。

我能够手动隔离列名并在每个名称下列出报告#,但我想动态找出不同的名称,使它们成为列名,并列出相应的报告。

所以我创建了一个程序,可以找到不同的名称并输出正确的代码。现在我很难将过程的结果插入到查询中。上面的链接没有任何帮助,(它似乎跳过了这一步)。

所以这里是手动方式的代码:

SELECT `DATE`, 
GROUP_CONCAT(CASE `Name` WHEN 'Name1' THEN `Report` END) AS 'Name1', 
GROUP_CONCAT(CASE `Name` WHEN 'Name2' THEN `Report` END) AS 'Name2' 
FROM `report_db` GROUP BY `DATE` ORDER BY `DATE`;

这是动态打印数据库中所有不同名称的 GROUP_CONCAT(... 的代码:

DROP PROCEDURE IF EXISTS writecountpivot;
DELIMITER | 
CREATE PROCEDURE writecountpivot( db CHAR(64), tbl CHAR(64), col CHAR(64) ) 
BEGIN 
DECLARE datadelim CHAR(1) DEFAULT '"'; 
DECLARE singlequote CHAR(1) DEFAULT CHAR(39); 
DECLARE comma CHAR(1) DEFAULT ','; 
SET @sqlmode = (SELECT @@sql_mode); 
SET @@sql_mode=''; 
  SET @sql = CONCAT( 'SELECT DISTINCT CONCAT(', singlequote, 
                     ',group_concat(IF(', col, ' = ', datadelim, singlequote, comma, 
                     col, comma, singlequote, datadelim, comma, '`IR NO`,null)) AS `',  
                     singlequote, comma, col, comma, singlequote, '`', singlequote,  
                     ') AS countpivotarg FROM ', db, '.', tbl, 
                     ' WHERE ', col, ' IS NOT NULL' ); 
  -- UNCOMMENT TO SEE THE MIDLEVEL CODE: 
  -- SELECT @sql;  
  PREPARE stmt FROM @sql; 
  EXECUTE stmt; 
  DROP PREPARE stmt; 
  SET @@sql_mode=@sqlmode; 
END
| 
DELIMITER ; 
CALL writecountpivot('database','`report_db`','name');

上面代码的结果是这样的

,group_concat(IF(name = "Name1",`IR NO`,null)) AS `Name1`
,group_concat(IF(name = "Name2",`IR NO`,null)) AS `Name2`
,group_concat(IF(name = "Name3",`IR NO`,null)) AS `Name3`

** 那么我该如何获取这个文本并将其插入到我的 SQL 中呢?如何将过程和查询放在一起?**

【问题讨论】:

    标签: mysql pivot crosstab


    【解决方案1】:

    很难准确说出您要执行的操作,但如果您尝试创建一个可以执行任意枢轴的过程,那么您需要为其提供更多参数(例如要旋转的对象以及可以在其中找到值的列)。

    此外,您需要在准备好的语句中创建准备好的语句。最外面的语句将使用GROUP_CONCAT() 构造要执行的GROUP_CONCAT() 表达式,基于指定列中的唯一值:

    CREATE FUNCTION SQL_ESC(_identifier VARCHAR(64))
    RETURNS VARCHAR(130) DETERMINISTIC
    RETURN CONCAT('`',REPLACE(_identifier,'`','``'),'`')//
    
    CREATE PROCEDURE writecountpivot(
      IN _db_nm VARCHAR(64),
      IN _tb_nm VARCHAR(64),
      IN _cl_gp VARCHAR(64),
      IN _cl_pv VARCHAR(64),
      IN _cl_vl VARCHAR(64)
    ) BEGIN
      SET @sql := CONCAT(
        "SELECT CONCAT('
                  SELECT   ",SQL_ESC(_cl_gp),",',
                  GROUP_CONCAT(DISTINCT CONCAT(
                    'GROUP_CONCAT(IF(",
                       SQL_ESC(_cl_pv),"=',QUOTE(",SQL_ESC(_cl_pv),"),'
                     , ",SQL_ESC(_cl_vl),"
                     , NULL
                     )) AS ',SQL_ESC(",SQL_ESC(_cl_pv),")
                  )), '
                  FROM     ",SQL_ESC(_db_nm),".",SQL_ESC(_tb_nm),"
                  GROUP BY ",SQL_ESC(_cl_gp),"
                ')
         INTO   @sql
         FROM   ",SQL_ESC(_db_nm),".",SQL_ESC(_tb_nm)
      );
    
      PREPARE stmt FROM @sql; 
      EXECUTE stmt; 
      DEALLOCATE PREPARE stmt;
    
      PREPARE stmt FROM @sql; 
      EXECUTE stmt; 
      DEALLOCATE PREPARE stmt;
    END//
    

    sqlfiddle 上查看。

    【讨论】:

    • 嗯....谢谢。我应该想到的是:使用过程将过程的结果插入到 SQL 代码中,或者将两个过程组合在一起并执行。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-06
    相关资源
    最近更新 更多