2013-10-22 21 views
13

同じ種類のデータを含む9列のデータベースを持つテーブルがあります。これらの値はで、NULLはです。 NULL以外の各値を、元の行のIDを気にしない値の単一の列に選択する必要があります。複数の列から単一の列に値を選択

ので、次のようになり、テーブルのために:

+---------+------+--------+------+ 
| Id | I1 | I2  | I3 | 
+---------+------+--------+------+ 
| 1 | x1 | x2  | x7 | 
| 2 | x3 | null | x8 | 
| 3 | null | null | null| 
| 4 | x4 | x5  | null| 
| 5 | null | x6  | x9 | 
+---------+------+--------+------+ 

私は、単一の列にXが付いた値のそれぞれを選択したいです。結果のデータは次の表のようになります。順序は保存する必要がありますので、最初の行から1列目の値が上下の最後の行から最後の列の値にする必要があります:私はSQL Server 2008を使用しています

+-------+ 
| value | 
+-------+ 
| x1 | 
| x2 | 
| x7 | 
| x3 | 
| x8 | 
| x4 | 
| x5 | 
| x6 | 
| x9 | 
+-------+ 

R2 。順番に各列の値を選択し、各行から値を選択し、結果にnull以外の値を挿入するよりも、これを達成するためのより良い手法がありますか?

答えて

17

はあなたが最終的な結果を得るためにUNPIVOTの機能を使用することができます。

select value 
from yourtable 
unpivot 
(
    value 
    for col in (I1, I2, I3) 
) un 
order by id, col; 

は、SQL Server 2008+、その後のことができますを使用しているのでVALUES句にCROSS APPLYを使用して列をピボット解除することもできます。

select value 
from yourtable 
cross apply 
(
    values 
     ('I1', I1), 
     ('I2', I2), 
     ('I3', I3) 
) c(col, value) 
where value is not null 
order by id, col 
+8

ここで重要なことは、[現在の最高回答の回答](http://stackoverflow.com/a/19515927/61305)とは異なり、発生するフルテーブルスキャンの回数を最小限に抑えることです(1対3 )。また、5列、8列、または22列の場合は、その数に応じてスキャン数が増えます。また、UNIONバージョンの照会は、書き込み/表示の方がはるかに面倒です。 –

5
SELECT value FROM (
    SELECT ID, 1 AS col, I1 AS [value] FROM t 
    UNION ALL SELECT ID, 2, I2 FROM t 
    UNION ALL SELECT ID, 3, I3 FROM t 
) AS t WHERE value IS NOT NULL ORDER BY ID, col; 
2

てみ組合下記のように:

select value from 
(
    select col1 as value from TestTable 
    union 
    select col2 as value from TestTable 
    union 
    select col3 as value from TestTable 
) tt where value is not null 
関連する問題