如何在SQL中将行转换为列

时间:2011-04-13 16:15:55

标签: sql tsql

有人可以帮我解决这个SQL查询问题。

在下表中,RESPONSES计算SEGMENT的次数 在CHECKED日期回复。

CREATE TABLE #TEST (ID INT, SEGMENT CHAR(1),RESPONSES
INT,CHECKED SMALLDATETIME)
INSERT INTO #TEST VALUES (1,'A',0,'2009-05-01')
INSERT INTO #TEST VALUES (2,'B',1,'2009-05-01')
INSERT INTO #TEST VALUES (3,'C',0,'2009-05-01')
INSERT INTO #TEST VALUES (4,'A',0,'2009-05-02')
INSERT INTO #TEST VALUES (5,'B',2,'2009-05-02')
INSERT INTO #TEST VALUES (6,'C',1,'2009-05-02')
INSERT INTO #TEST VALUES (7,'A',1,'2009-05-03')
INSERT INTO #TEST VALUES (8,'B',0,'2009-05-03')
INSERT INTO #TEST VALUES (9,'C',2,'2009-05-03')

撰写查询以总结每个SEGMENT和每个SEGMENT的总回复 检查日期,如下所示:

CHECKED      A      B       C
2009-5-01    0      1       0
2009-5-02    0      2       1
2009-5-03    1      0       2

不要将段名称(即“A”,“B”,“C”)硬编码到解决方案中,因此 如果添加更多片段(例如“D”)或片段,则解决方案保持有效 重命名(例如“A” - >“X”)。

3 个答案:

答案 0 :(得分:2)

您需要使用动态SQL。有关示例,请参阅此blog postAnother example,不同的博客,同样的方法。

如果您的列是静态的并且您使用的是SQL Server 2005及更高版本,则可以使用PIVOT功能来执行此类查询。

答案 1 :(得分:2)

Select Checked
    , Sum( Case When Segment = 'A' Then 1 Else 0 End ) As A
    , Sum( Case When Segment = 'B' Then 1 Else 0 End ) As B
    , Sum( Case When Segment = 'C' Then 1 Else 0 End ) As C
From #Test
Group By Checked

此类查询通常称为交叉表查询。上述解决方案假定您要静态声明要查看的列。如果要动态确定列,那么您所寻求的是动态交叉表,并且它无法在SQL语言中本机完成。 SQL语言不是为动态列生成而设计的。解决方案是在中间层构建查询。

答案 2 :(得分:1)

请在StackOverFlow上看到:如果使用的是SQL Server 2005或更高版本......

DECLARE  @test TABLE
(
    ID INT, 
    SEGMENT CHAR(1),
    RESPONSES INT,
    CHECKED SMALLDATETIME
)

INSERT INTO @test VALUES (1,'A',0,'2009-05-01')
INSERT INTO @test VALUES (2,'B',1,'2009-05-01')
INSERT INTO @test VALUES (3,'C',0,'2009-05-01')
INSERT INTO @test VALUES (4,'A',0,'2009-05-02')
INSERT INTO @test VALUES (5,'B',2,'2009-05-02')
INSERT INTO @test VALUES (6,'C',1,'2009-05-02')
INSERT INTO @test VALUES (7,'A',1,'2009-05-03')
INSERT INTO @test VALUES (8,'B',0,'2009-05-03')
INSERT INTO @test VALUES (9,'C',2,'2009-05-03')


SELECT * FROM 
(    
    SELECT  SEGMENT,
            RESPONSES,
            CHECKED
    FROM @test
) AS subquery 
PIVOT 
(
    SUM(responses) 
    FOR SEGMENT IN ([a],[b],[c])
) AS pivotquery

动态SQL示例

CREATE TABLE ##test
(
    ID INT, 
    SEGMENT CHAR(1),
    RESPONSES INT,
    CHECKED SMALLDATETIME
)

INSERT INTO ##test VALUES (1,'A',0,'2009-05-01')
INSERT INTO ##test VALUES (2,'B',1,'2009-05-01')
INSERT INTO ##test VALUES (3,'C',0,'2009-05-01')
INSERT INTO ##test VALUES (4,'A',0,'2009-05-02')
INSERT INTO ##test VALUES (5,'B',2,'2009-05-02')
INSERT INTO ##test VALUES (6,'C',1,'2009-05-02')
INSERT INTO ##test VALUES (7,'A',1,'2009-05-03')
INSERT INTO ##test VALUES (8,'B',0,'2009-05-03')
INSERT INTO ##test VALUES (9,'C',2,'2009-05-03')

DECLARE @SQLa VARCHAR(255),
        @SQLb VARCHAR(255),
        @SQLc VARCHAR(255)

SET @SQLa =
'SELECT * FROM 
(    
    SELECT  SEGMENT,
            RESPONSES,
            CHECKED
    FROM ##test
) AS subquery 
PIVOT 
(
    SUM(responses) 
    FOR SEGMENT IN ('

SET @SQLc = ')
) AS pivotquery'

SELECT @sqlB = STUFF(
(
    SELECT ',[' + SEGMENT + ']'
    FROM ##test WITH (NOLOCK)
    GROUP BY SEGMENT
    FOR XML PATH('')
),1, 1, '')

EXECUTE (@SQLa + @SQLb + @SQLc)

DROP TABLE ##test