2012-12-22 48 views
1

我知道這個問題或其方差已被多次詢問,而且我甚至嘗試過實施解決方案,但我很難完成它。如何將MySQL用於動態數據透視表或交叉表

我有一個非常簡單的表,有三個數據列: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 @@[email protected]; 
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?我怎麼把程序和查詢放在一起?**

回答

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

+0

嗯....謝謝。我應該想到:使用一個過程在SQL代碼中插入過程的結果,或將兩個過程組合在一起並執行。 – user139301