1

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

我有一个非常简单的表,其中包含三个数据列: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 中呢?如何将过程和查询放在一起?**

4

1 回答 1

3

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

此外,您将需要从准备好的语句中创建准备好的语句。最外面的语句将用于根据指定列中的唯一值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上查看。

于 2012-12-23T00:28:40.293 回答