2013-02-12 47 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; 

好运。