2013-02-26 14 views
6

Mam tabelę sql z bieżącą wartością i poprzednią wartością.Serwer SQL konwertuje kolumny do wierszy

Id Value1 PValue1 Value2 PValue2 
1 A  A  V  V1 
2 B  B1  W  W1 
3 C  C1  X  X 

Chcę je porównać i wyświetlić w poniższej tabeli, jeśli wartość została zmieniona.

Id Column Value Pvalue 
1 Value2 V  V1 
2 Value1 B  B1 
2 Value2 W  W1 
3 Value1 C  C1 

Czy jest to możliwe w SQL 2008 bez pętli dla każdej kolumny?

Odpowiedz

10

Można użyć CROSS APPLY do UNPIVOT dane:

SELECT t.id, 
    x.Col, 
    x.Value, 
    x.PValue 
FROM YourTable t 
CROSS APPLY 
(
    VALUES 
     ('Value1', t.Value1, t.PValue1), 
     ('Value2', t.Value2, t.PValue2) 
) x (Col, Value, PValue) 
where x.Value <> x.PValue; 

Zobacz SQL Fiddle with Demo.

Tylko dlatego, że kocham za pomocą przegubu funkcję , tutaj jest zarówno wersja używa UNPIVOT i pivot funkcje, aby uzyskać wynik:

select id, 
    colname, 
    value, 
    pvalue 
from 
(
    select id, 
    replace(col, 'P', '') colName, 
    substring(col, 1, PatIndex('%[0-9]%', col) -1) new_col, 
    val 
    from yourtable 
    unpivot 
    (
    val 
    for col in (Value1, PValue1, Value2, PValue2) 
) unpiv 
) src 
pivot 
(
    max(val) 
    for new_col in (Value, PValue) 
) piv 
where value <> pvalue 
order by id 

Zobacz SQL Fiddle with Demo

+0

+1, ponieważ nie wiedziałem, że możesz użyć CROSS APPLY w ten sposób! –

+0

+1 za posiadanie niebieskiego ... err Mam na myśli zapewnienie skrzypce SQL. – Kermit

+0

dzięki, jest bardzo przydatne. – developer

6

Oto prosty sposób:

SELECT Id, 
     'Value1' [Column], 
     Value1 Value, 
     PValue1 PValue 
FROM YourTable 
WHERE ISNULL(Value1,'') != ISNULL(PValue1,'') 
UNION ALL 
SELECT Id, 
     'Value2' [Column], 
     Value2 Value, 
     PValue2 PValue 
FROM YourTable 
WHERE ISNULL(Value2,'') != ISNULL(PValue2,'') 
+0

+1 - Pokonaj mnie! – JNK

+0

dzięki za szybką odpowiedź. – developer

0

Co powiesz na używanie związku:

SELECT * FROM 
    (SELECT Id, 'Value1' [Column], Value1 [Value], PValue1 [PValue] 
    FROM table_name 
    UNION ALL 
    SELECT Id, 'Value2' [Column], Value2 [Value], PValue2 [PValue] 
    FROM table_name)tmp 
WHERE Value != PValue 
ORDER BY Id 
0

Wreszcie, dla kompletności, istnieje polecenie UNPIVOT. Ponieważ jednak masz dwie kolumny, które chcesz rozpiąć, prawdopodobnie łatwiej byłoby użyć jednego z innych rozwiązań.