2013-10-22 25 views
13

Mam tabelę w bazie danych, która ma 9 kolumn zawierających ten sam rodzaj danych, te wartości to , które mogą mieć wartość null. Muszę wybrać każdą z wartości innych niż null w jednej kolumnie wartości, które nie dbają o tożsamość wiersza, z którego pochodzą.Wybieranie wartości z wielu kolumn do pojedynczej kolumny

Tak, dla tabeli, która wygląda następująco:

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

życzę, aby wybrać każdy z wartościami z prefiksem X w jednej kolumnie. Moje wynikowe dane powinny wyglądać jak poniższa tabela. Porządek musi być zachowana, więc pierwsza wartość kolumny z pierwszym rzędzie powinny być na górze i na ostatniej wartości kolumny z ostatniego rzędu na dole:

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

Używam SQL Server 2008 R2 . Czy istnieje lepsza technika osiągnięcia tego, niż wybór wartości każdej kolumny po kolei z każdego wiersza i wstawienie wartości niepustych do wyników?

Odpowiedz

17

Można użyć funkcji UNPIVOT aby uzyskać ostateczny wynik:

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

Ponieważ używasz SQL Server 2008+, to można użyj również CROSS APPLY z klauzulą ​​VALUES, aby rozpiąć kolumny:

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

Należy tutaj zwrócić uwagę na to, że w przeciwieństwie do [obecnie najwyższych głosów] (http://stackoverflow.com/a/19515927/61305), minimalizują one liczbę pełnych skanów tabeli (1 do 3)). A jeśli masz 5 kolumn, 8 kolumn lub 22 kolumny, to oba zwiększają liczbę skanów do tej liczby, a także sprawiają, że wersja UNION zapytania jest znacznie bardziej kłopotliwa do napisania/spojrzenia. –

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

Spróbuj unia jak poniżej:

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 
Powiązane problemy