2013-02-01 65 views
0

我有N列的表:SQL Server查询 - 透视后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子句尝试了多个select,但由于我返回了很多记录,所以速度并不快。有没有更好的方法来'旋转'这个表2列?

谢谢。

+0

如何计数为每列或价值的计算? – TechDo

+0

你可以从你的表中发布一些示例数据吗?很难说出理想的结果。 – Taryn

+0

@techdo它是另一个保存这些信息的应用程序 –

回答

3

这也可以使用CROSS APPLYVALUES声明进行:

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); 

SQL Fiddle with Demo

这里是解释如何做到这一点(需要注册)的一篇文章:

http://www.sqlservercentral.com/articles/CROSS+APPLY+VALUES+UNPIVOT/91234/

+0

不错的解决方案。虽然,你发布的链接需要注册,这有点痛苦...... – codingbadger

1

你可以UNPIVOT,然后转动数据,它可能会表现得更好:

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操作将有更好的表现。我仍然建议您同时测试两者,以查看哪种数据最适合您。

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; 
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