2013-02-12 51 views
1

我有這樣的SQL視圖:SQL行轉換成列的數據透視表

id date_from date_to 
1 2005-01-05 2005-05-10 
1 2005-01-05 2005-05-10 
1 2005-01-05 2005-05-10 
2 2005-01-01 2006-08-31 
2 2010-01-01 2010-06-30 
3 2005-01-01 2005-06-30 

我想寫它返回的SQL語句:

1 2005-01-05 2005-05-10 2005-01-05 2005-05-10 2005-01-05 2005-05-10 
2 2005-01-01 2006-08-31 2010-01-01 2010-06-30 NULL  NULL 
3 2005-01-01 2005-06-30 NULL  NULL  NULL  NULL 

任何想法?

+3

其中RDBMS是這樣的 - MySQL和甲骨文,SQLServer的......?此外,你是否會想要每個ID超過三個date_from,date_to對? – 2013-02-12 17:16:59

+0

從你在標題和標籤中放置「pivot」的事實來看,你顯然已經有了一個想法,顯然它不起作用。它出了什麼問題?而且,你正在使用什麼DBMS? – ruakh 2013-02-12 17:17:35

+0

我正在使用Teradata。視圖在同一個案例中可以有3個以上的日期,但我想使用3個最新的日期。 – 2013-02-12 18:47:39

回答

1

馬克問題的答案將有所幫助。

哪個RDBMS是這個 - MySQL,Oracle,SQLServer ...?此外,你有沒有想要超過三個date_from,date_to對每個ID?

使用t-sql,我明確地處理了3個級別。如果您希望它是動態的,則需要動態創建查詢。

DECLARE @staging TABLE 
(
    id int NOT NULL, 
    date_from datetime NOT NULL, 
    date_to datetime NOT NULL, 
    step int 
) 

INSERT INTO @staging 
SELECT id, date_from, date_to, 
    ROW_NUMBER() OVER(PARTITION BY id ORDER BY date_from, date_to) 
FROM tblTemp 

-- below is static for 3 levels, make below dynamic to match what you want 
SELECT t1.id, t1.date_from, t1.date_to, t2.date_from, t2.date_to, t3.date_from, t3.date_to 
FROM @staging t1 LEFT OUTER JOIN 
    @staging t2 ON t1.id = t2.id AND t2.step = 2 LEFT OUTER JOIN 
    @staging t3 ON t2.id = t3.id AND t3.step = 3 
WHERE t1.step = 1 

測試@http://sqlfiddle.com/#!3/9daae/4/0

+0

謝謝,它看起來不錯。我明天將在Teradata上嘗試。 – 2013-02-12 18:56:30

+0

@PetrNovák,我是teradata的新手。我剛剛確認幾乎所有上述內容都可以使用。唯一可疑的部分是臨時表。 – 2013-02-12 19:12:03

+0

您可以將臨時表聲明爲Teradata中的VOLATILE TABLE,它將在用戶的SPOOL空間中創建。 – 2013-02-12 20:16:31

1

因爲你最近的問題都與MySQL有關,所以我假設你需要一個MySQL解決方案。

如果您知道潛在日期範圍的最大數量,那麼您可以使用MAX和CASE。然而,你必須有一個行計數器,因爲你沒有任何其他的唯一標識符(我實際上建議將它添加到你的視圖,因爲你提到這是一個視圖)。這雖然:

SELECT Id, 
    MAX(CASE WHEN row_number = 1 THEN date_from END) date_from1, 
    MAX(CASE WHEN row_number = 1 THEN date_to END) date_to1, 
    MAX(CASE WHEN row_number = 2 THEN date_from END) date_from2, 
    MAX(CASE WHEN row_number = 2 THEN date_to END) date_to2, 
    MAX(CASE WHEN row_number = 3 THEN date_from END) date_from3, 
    MAX(CASE WHEN row_number = 3 THEN date_to END) date_to3 
FROM (
    SELECT 
     id, 
     @running:=if(@previous=id,@running,0) + 1 as row_number, 
     @previous:=id, 
     date_from, date_to 
    FROM YourView 
     JOIN (SELECT @previous := 0) r 
    ORDER BY id, date_from, date_to 
) t 
GROUP BY Id 

如果你不知道的日期範圍的最大數,那麼你將無法使用一個SQL語句來做到這一點。相反,您需要使用動態SQL。

我假設你可以將ROW_NUMBER添加到您的視圖,這裏是一個緊密例如:

SET @sql = NULL; 
SELECT 
    GROUP_CONCAT(DISTINCT 
    CONCAT(
     'MAX(CASE WHEN row_number = ', 
     row_number, 
     ' THEN date_from END) date_from', 
     row_number) 
), 
    GROUP_CONCAT(DISTINCT 
    CONCAT(
     'MAX(CASE WHEN row_number = ', 
     row_number, 
     ' THEN date_to END) date_to', 
     row_number) 
) INTO @sql 
FROM YourView; 

SET @sql = CONCAT('SELECT ID, ', 
        @sql, ' 
        FROM YourView 
        GROUP BY ID'); 

PREPARE stmt FROM @sql; 
EXECUTE stmt; 
DEALLOCATE PREPARE stmt; 

好運。