使用sql转换表的视图

时间:2015-06-16 14:47:58

标签: sql sql-server database

我有下表

Date    Input   Output  Rate 
10/10/2001  10  15  0.5
10/11/2002  13  14  0.3

 1. Date    Input   Output  Rate 
 2. 10/10/2001  10  15  0.5
 3. 10/11/2002  13  14  0.3

我需要在下表中转换此表:

 1. Date    Category    Amount
 2. 10/10/2001  Input   10 
 3. 10/10/2001  Output  15
 4. 10/10/2001  Rate    0.5
 5. 10/11/2002  Input   13
 6. 10/11/2002  Output  14
 7. 10/11/2002  Rate    0.3

我应该使用哪种查询?

提前谢谢。

2 个答案:

答案 0 :(得分:1)

您可以使用UNPIVOT

DECLARE @T TABLE (Date DATE, Input DECIMAL(5, 1), [Output] DECIMAL(5, 1), Rate DECIMAL(5, 1));
INSERT @T VALUES ('20011010', 10, 15, 0.5), ('20021110', 13, 14, 0.3);

SELECT  upvt.Date, upvt.Category, upvt.Amount
FROM    @T 
        UNPIVOT
        (   Amount
            FOR Category IN ([input], [Output], [Rate])
        ) upvt;

但是,我更喜欢稍微更灵活的CROSS APPLYtable valued constructor

DECLARE @T TABLE (Date DATE, Input DECIMAL(5, 1), [Output] DECIMAL(5, 1), Rate DECIMAL(5, 1));
INSERT @T VALUES ('20011010', 10, 15, 0.5), ('20021110', 13, 14, 0.3);

SELECT  t.Date, upvt.Category, upvt.Amount
FROM    @T AS t
        CROSS APPLY
        (VALUES
            ('Input', t.Input),
            ('Output', t.[Output]),
            ('Rate', t.Rate)
        ) AS upvt (Category, Amount);

因为它为您的数据类型转换提供了更大的灵活性,并且您的列重命名略有不同,例如像CallStartTime之类的Call Start这样的列更容易,因此它更适合报告。

例如,如果您的输入和输出列实际上是整数,则在使用UNPIVOT时会收到错误消息:

  

“Rate”列的类型与UNPIVOT列表中指定的其他列的类型冲突。

因此您需要使用子查询,并将列转换为:

DECLARE @T TABLE (Date DATE, Input INT, [Output] INT, Rate DECIMAL(5, 1));
INSERT @T VALUES ('20011010', 10, 15, 0.5), ('20021110', 13, 14, 0.3);

SELECT  upvt.Date, upvt.Category, upvt.Amount
FROM    (   SELECT  Date,
                    Input = CONVERT(DECIMAL(5, 1), Input),
                    [Output] = CONVERT(DECIMAL(5, 1), [Output]),
                    Rate
            FROM    @T 
        ) AS t
        UNPIVOT
        (   Amount
            FOR Category IN ([input], [Output], [Rate])
        ) upvt;

虽然你必须使用CROSS APPLY做同样的转换,但对我来说似乎不那么混乱:

DECLARE @T TABLE (Date DATE, Input INT, [Output] INT, Rate DECIMAL(5, 1));
INSERT @T VALUES ('20011010', 10, 15, 0.5), ('20021110', 13, 14, 0.3);

SELECT  t.Date, upvt.Category, upvt.Amount
FROM    @T AS t
        CROSS APPLY
        (VALUES
            ('Input', CONVERT(DECIMAL(5, 1), Input)),
            ('Output', CONVERT(DECIMAL(5, 1), [Output])),
            ('Rate', t.Rate)
        ) AS upvt (Category, Amount);

这当然是个人偏好。

答案 1 :(得分:1)

您可以使用每个DBMS支持的简单标准SQL UNION ALL - >便携式: - )

SELECT  Date, 'Input' AS Category, Cast(Input as DEC(5,1)) AS Amount
FROM    Tab
UNION ALL
SELECT  Date, 'Output' AS Category, Output
FROM    Tab
UNION ALL
SELECT  Date, 'Rate' AS Category, Rate
FROM    Tab