我有一个包含N列的表:
TABLE:
TB_SAMPLE
COLUMNS:
VALUE_A
COUNT_A
VALUE_B
COUNT_B
VALUE_C
COUNT_C
VALUE_D
COUNT_D
VALUE_E
COUNT_E
VALUE_F
COUNT_F
VALUE_G
COUNT_G
VALUE_H
COUNT_H
VALUE_I
COUNT_I
我想这样回来:
'Value', 'Count'
A, 1 -- this is the first and the second column
B, 3 -- this is the third and the fourth column
C, 4 -- this is the fifth and sixth column
等等。我已尝试使用UNION ALL子句进行多次选择,但由于我返回了大量记录,因此速度并不快。有没有更好的方法来“旋转”这个表2列?
感谢。
答案 0 :(得分:3)
也可以使用带有CROSS APPLY
声明的VALUES
执行此操作:
SELECT vals, counts
FROM temp t
CROSS APPLY
(
VALUES
(value_a, count_a),
(value_b, count_b),
(value_c, count_c),
(value_d, count_d),
(value_e, count_e),
(value_f, count_f),
(value_g, count_g),
(value_h, count_h)
) x (vals, counts);
这是一篇解释如何完成此操作的文章(需要注册):
http://www.sqlservercentral.com/articles/CROSS+APPLY+VALUES+UNPIVOT/91234/
答案 1 :(得分:1)
你可以UNPIVOT,然后PIVOT数据,它可能表现更好:
DECLARE @T TABLE
( VALUE_A INT, COUNT_A INT, VALUE_B INT, COUNT_B INT, VALUE_C INT, COUNT_C INT, VALUE_D INT, COUNT_D INT, VALUE_E INT,
COUNT_E INT, VALUE_F INT, COUNT_F INT, VALUE_G INT, COUNT_G INT, VALUE_H INT, COUNT_H INT, VALUE_I INT, COUNT_I INT
);
INSERT @T VALUES (1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1);
WITH D AS
( SELECT Category = SUBSTRING(B, 7, LEN(B)), [Type] = 'Value', A
FROM @T
UNPIVOT
( A
FOR B IN ([VALUE_A], [VALUE_B], [VALUE_C], [VALUE_D], [VALUE_E], [VALUE_F], [VALUE_G], [VALUE_H], [VALUE_I])
) upvt
UNION ALL
SELECT Category = SUBSTRING(B, 7, LEN(B)), [Type] = 'Count', A
FROM @T
UNPIVOT
( A
FOR B IN ([COUNT_A], [COUNT_B], [COUNT_C], [COUNT_D], [COUNT_E], [COUNT_F], [COUNT_G], [COUNT_H], [COUNT_I])
) upvt
)
SELECT *
FROM D
PIVOT
( SUM(A)
FOR [Type] IN ([Value], [Count])
) pvt;
如果需要,您也可以通过查询列名称的系统视图来动态执行此操作。
<强>附录强>
刚刚意识到这可以通过连接而不是UNION和PIVOT实现,我想联接会在删除PIVOT操作时表现更好。我仍然建议测试两者,看看哪种方法最适合您的数据。
WITH Val AS
( SELECT Category = SUBSTRING(B, 7, LEN(B)), A
FROM @T
UNPIVOT
( A
FOR B IN ([VALUE_A], [VALUE_B], [VALUE_C], [VALUE_D], [VALUE_E], [VALUE_F], [VALUE_G], [VALUE_H], [VALUE_I])
) upvt
), Co AS
( SELECT Category = SUBSTRING(B, 7, LEN(B)), A
FROM @T
UNPIVOT
( A
FOR B IN ([COUNT_A], [COUNT_B], [COUNT_C], [COUNT_D], [COUNT_E], [COUNT_F], [COUNT_G], [COUNT_H], [COUNT_I])
) upvt
)
SELECT val.Category,
[Value] = val.A,
[Count] = co.A
FROM val
INNER JOIN co
ON co.Category = val.Category;
答案 2 :(得分:1)
这是另一种方法(如果我已正确理解你的问题)
declare @table table
(
value_a varchar(10),
count_a int,
value_b varchar(10),
count_b int,
value_c varchar(10),
count_c int,
value_d varchar(10),
count_d int,
value_e varchar(10),
count_e int,
value_f varchar(10),
count_f int,
value_g varchar(10),
count_g int,
value_h varchar(10),
count_h int
)
Insert Into @table
Select 'value a',675,
'value b',646,
'value c',13,
'value d',22,
'value e',768,
'value f',223,
'value g',66,
'value h',55
SELECT vals,
counts
FROM
(
SELECT *
FROM @table
) p
UNPIVOT
(vals FOR cols IN
([value_a],[value_b],[value_c],[value_d], [value_e],[value_f],[value_g],[value_h])
)AS unpvtValues
Unpivot
(
counts for counters in ([count_a],[count_b],[count_c], [count_d],[count_e],[count_f],[count_g],[count_h])
) as unpvtCounts
where Right(cols, 2) = right(counters, 2)
修改强>
如果你想使用一些动态SQL,你可以使用这个选项(这会在你的数据库中创建一个合适的表,而不是使用表变量)
create Table dbo.TempTable
(
value_a varchar(10),
count_a int,
value_b varchar(10),
count_b int,
value_c varchar(10),
count_c int,
value_d varchar(10),
count_d int,
value_e varchar(10),
count_e int,
value_f varchar(10),
count_f int,
value_g varchar(10),
count_g int,
value_h varchar(10),
count_h int
)
Insert Into dbo.TempTable
Select 'value a',675,
'value b',646,
'value c',13,
'value d',22,
'value e',768,
'value f',223,
'value g',66,
'value h',55
Declare @ValueCols varchar(max),
@CountCols varchar(max),
@sql varchar(max)
Select @ValueCols = Coalesce(@ValueCols + ', ','') + '[' + Column_Name +']'
From INFORMATION_SCHEMA.COLUMNS
Where TABLE_NAME = 'TempTable'
And COLUMN_NAME Like 'Value%'
Select @CountCols = Coalesce(@CountCols + ', ','') + '[' + Column_Name +']'
From INFORMATION_SCHEMA.COLUMNS
Where TABLE_NAME = 'TempTable'
And COLUMN_NAME Like 'Count%'
Set @sql = 'SELECT vals,
counts
FROM
(
SELECT *
FROM dbo.TempTable
) p
UNPIVOT
(vals FOR cols IN
(' + @ValueCols +')
)AS unpvtValues
Unpivot
(
counts for counters in (' + @CountCols + ')
) as unpvtCounts
where Right(cols, 2) = right(counters, 2)'
Execute (@sql)
drop table TempTable