简体   繁体   English

如何使用MySQL作为动态数据透视表或交叉表

[英]how to use MySQL for a dynamic pivot table or crosstab

I know this question or a variance thereof has been asked multiple times, and I have even tried implementing a solution, but I am struggling in completing it. 我知道这个问题或其差异已被多次询问,我甚至尝试过实施解决方案,但我正在努力完成它。

I have a very simple table with three data columns: Date1, Report_#, Name. 我有一个非常简单的表,有三个数据列:Date1,Report_#,Name。 I would like to pivot it around Date and the various names as the header tab, and have all the report numbers appear below. 我想将其围绕日期和各种名称作为标题选项卡进行调整,并将所有报告编号显示在下方。

So it would LOOK like this: 所以看起来像这样:

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

I was able to get an idea of what to do from http://www.artfulsoftware.com/infotree/queries.php#78 but I'm stuck. 我能够从http://www.artfulsoftware.com/infotree/queries.php#78了解该怎么做,但我被卡住了。

I was able to isolate the column names manually and list the report # under each name, but I want to do dynamically figure out the distinct names, make them column names, and list the corresponding reports. 我能够手动隔离列名并在每个名称下列出报告#,但我想动态地找出不同的名称,使它们成为列名,并列出相应的报告。

So I created a procedure that would find distinct names and output the correct code. 所以我创建了一个程序,可以找到不同的名称并输出正确的代码。 Now I have a hard time plugging the results of the procedure onto the query. 现在我很难将过程的结果插入到查询中。 And the link above does not help whatsoever, (it seems to skip that step). 上面的链接没有任何帮助,(似乎跳过了这一步)。

So here is the code for the manual way: 所以这是手动方式的代码:

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`;

And here is the code that dynamic prints the GROUP_CONCAT(... for all the distinct names in the database: 这里是动态打印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');

and the result of the code above would be this 以上代码的结果就是这个

,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`

** So how do I take this text and plug it to my SQL? **那么如何将此文本插入我的SQL呢? How do I put the procedure and the query together?** 如何将程序和查询放在一起?**

It's difficult to tell exactly what it is you're trying to do, but if you're attempting to create a procedure that can perform arbitrary pivots then you'll need to provide it with more arguments (such as the column on which to pivot and the column in which values can be found). 很难确切地知道你正在尝试做什么,但是如果你试图创建一个可以执行任意枢轴的过程,那么你需要为它提供更多的参数(例如要转动的列以及可以找到值的列。

Furthermore, you will need to create a prepared statement from within a prepared statement. 此外,您需要在准备好的语句中创建预准备语句。 The outermost statement will use GROUP_CONCAT() to construct the GROUP_CONCAT() expressions that are to be executed, based on the unique values in the specified column: 最外层语句将使用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//

See it on sqlfiddle . sqlfiddle上看到它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM