如何在SQL中将行转换为列
有人能帮我处理这个SQL查询吗 在下表中,响应统计了段发生的次数 在检查日期回复如何在SQL中将行转换为列,sql,tsql,Sql,Tsql,有人能帮我处理这个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',
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')
编写一个查询,总结每个细分市场和每个细分市场的总响应
检查日期,以以下格式显示:
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”)。您需要使用动态SQL。看看这个例子。不同的博客,相同的方法
如果列是静态的,并且使用的是SQL Server 2005及更高版本,则可以使用该功能执行此类查询。您需要使用动态SQL。看看这个例子。不同的博客,相同的方法
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 Server 2005及更高版本,则可以使用该功能执行此类查询
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语言不是为动态列生成而设计的。解决方案是在中间层构建查询
这种类型的查询通常称为交叉表查询。上述解决方案假设您希望静态声明要查看的列。如果您想动态地确定列,那么您要寻找的是一个动态交叉表,而不能用SQL语言本机完成。SQL语言不是为动态列生成而设计的。解决方案是在中间层构建查询。请参见:如果使用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
请参阅:如果使用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
这有点家庭作业的味道。是吗?@paul-这是一个采访问题,我无法回答:p简短的回答是,不能用SQL语言本机完成。它要么需要特定于供应商的扩展(例如Access的转换关键字),要么需要动态SQL,这应该在T-SQL之外完成。这有点像家庭作业。是吗?@paul-这是一个采访问题,我无法回答:p简短的回答是,不能用SQL语言本机完成。它需要特定于供应商的扩展(例如Access的转换关键字)或动态SQL,而动态SQL应该在T-SQL之外完成。动态SQL是唯一的其他方法。查看编辑到我的答案中的链接。动态查询是唯一的方法。使用PIVOT时,要透视的列必须在查询中列出,即PIVOT查询不能处理“动态段”,即最后一个条件“不要硬编码段名称…”不能用静态语句实现。@amit\u g:好的。为了强调这一点,我对答案进行了反复分析。动态SQL是唯一的另一种方法。查看编辑到我的答案中的链接。动态查询是唯一的方法。使用PIVOT时,要透视的列必须在查询中列出,即PIVOT查询不能处理“动态段”,即最后一个条件“不要硬编码段名称…”不能用静态语句实现。@amit\u g:好的。我把我的答案翻了个底朝天来强调这一事实。非常感谢,但我不想要一个固定的专栏。还有别的办法吗??如果是K、L和M,我不想将A、B和C重命名为K、L和M。@Kevin——正如我在回答的底部所修正的那样,这不能用SQL语言本机完成。唯一的解决方案是动态SQL,这不应该在T-SQL中完成。非常感谢,但我不想要修复列。还有别的办法吗??如果是K、L和M,我不想将A、B和C重命名为K、L和M。@Kevin——正如我在回答的底部所修正的那样,这不能用SQL语言本机完成。唯一的解决方案是动态SQL,它不应该在T-SQL中完成。您可以使用动态SQL(或函数)获取列名:a、B、C-如果您想要示例,请告诉我。@dan-请告诉我示例。凯文:对不起,昨晚的会议耽搁了。不过,直到现在我才意识到这是一个面试问题。这是否意味着我得到了这份工作?:)你资历太高了。这意味着您不明白:p您可以使用动态SQL(或函数)获取列名:a、B、C-如果您想要一个示例,请告诉我。@dan-请告诉我示例。凯文:对不起,昨晚的会议耽搁了。不过,直到现在我才意识到这是一个面试问题。这是否意味着我得到了这份工作?:)你资历太高了。这意味着你不明白:P