2012-02-07 41 views
1

我有,我想加入,並在2008年SQL創建一個交叉表兩張表:的SQL Server 2008 +創建交叉表存儲過程

表A:

Auto_ID | Fiscal_Period | Amount 
    1  | 01012012  | NULL 
    1  | 01022012  | 80 
    1  | 01032012  | NULL 
    2  | 01012012  | NULL 
    2  | 01022012  | 10 

TABLEB:

Auto_ID | Row_ID | StaticData 
    1 | 1 | sampledata 
    2 | 2 | data1 

我想用交叉表動態創建下表結構:

Row_ID | StaticData | FiscalPeriod(01012012) | FiscalPeriod(01022012) | FiscalPeriod(01032012) 
    1 | sampledata | NULL     | 80      | NULL 
    2 | data1  | NULL     | 10      | NULL 

我當前的查詢正確加入表;但是,我很難將財政期間轉換爲我的標題行。

SELECT * 
FROM (SELECT 
     B.Row_Id as RowID, B.StaticData as StaticData, A.Fiscal_Period AS FPPD 
     FROM TableA A 
     LEFT JOIN TableB B ON A.Auto_ID = B.Auto_ID) 
+0

如果您發佈的代碼,XML或數據樣本,**請**突出顯示文本編輯器中的那些行並點擊編輯器工具欄上的「代碼示例」按鈕(「{}」),以精確地格式化和語法突出顯示它! (也絕對不需要大量' '或'
'元素,這樣....) – 2012-02-07 06:09:04

回答

2

這是我會做:

首先創建一些測試數據:

CREATE TABLE tblA (Auto_ID INT,Fiscal_Period VARCHAR(100),Amount FLOAT) 
CREATE TABLE tblB (Auto_ID INT,Row_ID INT,StaticData VARCHAR(100)) 
INSERT INTO tblA 
SELECT 1,'01012012',NULL UNION ALL 
SELECT 1,'01022012',80 UNION ALL 
SELECT 1,'01032012',NULL UNION ALL 
SELECT 2,'01012012',NULL UNION ALL 
SELECT 2,'01022012',10 

INSERT INTO tblB 
SELECT 1,1,'sampledata' UNION ALL 
SELECT 2,2,'data1' 

然後找到唯一列:

DECLARE @cols VARCHAR(MAX) 
;WITH CTE 
AS 
(
SELECT 
    ROW_Number() OVER(PARTITION BY tblA.Fiscal_Period ORDER BY tblA.Fiscal_Period) AS RowNbr, 
    tblA.Fiscal_Period 
FROM 
    tblA AS tblA 
) 
SELECT 
    @cols = COALESCE(@cols + ','+QUOTENAME('FiscalPeriod('+Fiscal_Period+')'), 
       QUOTENAME('FiscalPeriod('+Fiscal_Period+')')) 
FROM 
    CTE 
WHERE 
    CTE.RowNbr=1 

然後使用動態SQL執行一個支點:

DECLARE @query NVARCHAR(4000)= 
N'SELECT 
    * 
FROM 
(
SELECT 
    tblB.Row_ID, 
    tblb.StaticData, 
    ''FiscalPeriod(''+tblA.Fiscal_Period+'')'' AS Name, 
    tblA.Amount 
FROM 
    tblA AS tblA 
    JOIN tblB AS tblB 
     ON tblA.Auto_ID=tblB.Auto_ID 
) AS p 
PIVOT 
(
    SUM(Amount) 
    FOR Name IN ('[email protected]+') 
) AS Pvt' 
EXECUTE(@query) 

然後在我的情況下,我會刪除臨時表:

DROP TABLE tblA 
DROP TABLE tblB 

我希望這將有助於你

+0

謝謝,這工作很好!我喜歡CTE的使用:-) – user1130511 2012-02-07 18:52:54

+0

是的,它是非常簡單而明確的專欄。樂意效勞 :-) – Arion 2012-02-07 19:08:07

0

由於您沒有指定數據庫的風格,請注意,以下內容僅對MySQL有效!

交叉表查詢只能用一個非常髒的技巧才能實現,它只能在存儲過程中實用。

你首先想了一些辦法,來改變會計期間的名單到SQL,像

SELECT 
    TABLEB.Row_ID, 
    TABLEB.staticdata 
    ,fp01012012.Amount as fp01012012amount 
    ,fp01022012.Amount as fp01022012amount 
    ,fp01032012.Amount as fp01032012amount 
FROM 
    TABLEB 
    LEFT JOIN TableA AS fp01012012 ON fp01012012.Auto_ID=TABLEB.Auto_ID AND fp01012012.Fiscal_Period='01012012' 
    LEFT JOIN TableA AS fp01022012 ON fp01022012.Auto_ID=TABLEB.Auto_ID AND fp01022012.Fiscal_Period='01022012' 
    LEFT JOIN TableA AS fp01032012 ON fp01032012.Auto_ID=TABLEB.Auto_ID AND fp01032012.Fiscal_Period='01032012' 

,你現在必須建立動態SQL - 這是feasable只在一個存儲過程。

DELIMITER $$ 

DROP PROCEDURE IF EXISTS `create_fiscal_data`$$ 
CREATE PROCEDURE `create_fiscal_data`() 
BEGIN 
     DECLARE dynfields VARCHAR(10000) DEFAULT 'SELECT TABLEB.Row_ID, TABLEB.staticdata'; 
     DECLARE dynfrom VARCHAR(10000) DEFAULT ' FROM TABLEB'; 
     DECLARE period VARCHAR(10) DEFAULT ''; 
     DECLARE done INT DEFAULT 0; 
     DECLARE id INT DEFAULT 7; 
     DECLARE periods CURSOR FOR SELECT DISTINCT Fiscal_Period FROM TableA; 
     DECLARE CONTINUE HANDLER FOR NOT FOUND SET done=1; 
     OPEN periods; 

     cycleperiods: LOOP 
      FETCH periods INTO period; 
      IF done=1 THEN LEAVE cycleperiods; END IF; 

      SET dynfields=CONCAT(dynfields,',`fp',period,'`.Amount AS `fp',period,'amount`'); 
      SET dynfrom=CONCAT(dynfrom,' LEFT JOIN TableA AS `fp',period,'` ON `fp',period,'`.Auto_ID=TABLEB.Auto_ID AND `fp',period,'`.Fiscal_Period="',period,'"'); 

     END LOOP; 

     CLOSE periods; 

     SELECT @dynsql:=CONCAT(dynfields,dynfrom) INTO dynfields; 
     -- Here comes the trick! 
     PREPARE dynqry FROM @dynsql; 
     EXECUTE dynqry; 

END$$ 

DELIMITER ; 

的訣竅是,建立SQL插入變量@dynsql(DECLARE d變量都不行),然後準備並執行它。

現在查詢

CALL `create_fiscal_data;` 

將創建你所需要的輸出。

+0

感謝您的答覆,虐待嘗試將此轉換爲sql2008。對不起,我沒有在我的問題中指定。 – user1130511 2012-02-07 01:36:12

+0

應該很簡單 - 請寄回你的結果!我還在你的問題上編輯了標籤,使其更清晰。 – 2012-02-07 01:36:58