Szukasz eleganckiego (lub dowolnego) rozwiązania do konwersji kolumn na wiersze.
Oto przykład: Mam tabelę z następującym schematem:
[ID] [EntityID] [Indicator1] [Indicator2] [Indicator3] ... [Indicator150]
Oto, co chcę uzyskać jako wynik:
[ID] [EntityId] [IndicatorName] [IndicatorValue]
A wartościami wyniku będą:
1 1 'Indicator1' 'Value of Indicator 1 for entity 1'
2 1 'Indicator2' 'Value of Indicator 2 for entity 1'
3 1 'Indicator3' 'Value of Indicator 3 for entity 1'
4 2 'Indicator1' 'Value of Indicator 1 for entity 2'
I tak dalej..
Czy to ma sens? Czy masz jakieś sugestie, gdzie szukać i jak to zrobić w T-SQL?
sql
sql-server
tsql
unpivot
Siergiej
źródło
źródło
Odpowiedzi:
Możesz użyć funkcji UNPIVOT, aby przekonwertować kolumny na wiersze:
Zauważ, że typy danych kolumn, których nie obracasz, muszą być takie same, więc może być konieczne przekonwertowanie typów danych przed zastosowaniem unpivot.
Możesz również użyć
CROSS APPLY
UNION ALL, aby przekonwertować kolumny:W zależności od wersji programu SQL Server możesz nawet użyć CROSS APPLY z klauzulą VALUES:
Wreszcie, jeśli masz 150 kolumn do cofnięcia przestawienia i nie chcesz na stałe zakodować całego zapytania, możesz wygenerować instrukcję sql za pomocą dynamicznego SQL:
źródło
UNPIVOT
i / vs.APPLY
, ten post na blogu z 2010 roku autorstwa Brada Schulza (i jego następcy ) jest (są) piękny.cóż, jeśli masz 150 kolumn, myślę, że UNPIVOT nie wchodzi w grę. Więc możesz użyć sztuczki XML
sql fiddle demo
Mógłbyś też napisać dynamiczny SQL, ale ja bardziej lubię xml - dla dynamicznego SQL musisz mieć uprawnienia do wybierania danych bezpośrednio z tabeli, a to nie zawsze jest możliwe.
AKTUALIZACJA
Ponieważ komentarze są bardzo popularne, myślę, że dodam kilka zalet i wad XML / Dynamic SQL. Postaram się być jak najbardziej obiektywny i nie wspominać o elegancji i brzydocie. Jeśli masz inne za i przeciw, edytuj odpowiedź lub napisz w komentarzach
Cons
plusy
inserted
ideleted
tabele wewnątrz wyzwalacza (nie jest to w ogóle możliwe w przypadku dynamiki);źródło
Aby pomóc nowym czytelnikom, stworzyłem przykład, aby lepiej zrozumieć odpowiedź @ bluefeet na temat UNPIVOT.
źródło
Potrzebowałem rozwiązania do konwersji kolumn na wiersze w Microsoft SQL Server, bez znajomości nazw kolumn (używanych w wyzwalaczu) i bez dynamicznego sql (dynamiczny sql jest zbyt wolny do użycia w wyzwalaczu).
W końcu znalazłem to rozwiązanie, które działa dobrze:
Jak widać, konwertuję wiersz na XML (Subquery select i, * dla xml raw, to konwertuje wszystkie kolumny na jedną kolumnę xml)
Następnie CROSS STOSUJĘ funkcję do każdego atrybutu XML tej kolumny, tak aby uzyskać jeden wiersz na atrybut.
Ogólnie rzecz biorąc, konwertuje to kolumny na wiersze bez znajomości nazw kolumn i bez używania dynamicznego sql. Jest wystarczająco szybki jak na mój cel.
(Edycja: właśnie zobaczyłem powyżej odpowiedź Romana Pekara, który robi to samo. Najpierw użyłem dynamicznego wyzwalacza sql z kursorami, który był 10 do 100 razy wolniejszy niż to rozwiązanie, ale może było to spowodowane przez kursor, a nie przez dynamiczny sql. Zresztą to rozwiązanie jest bardzo proste i uniwersalne, więc definitywnie jest opcją).
Ten komentarz zostawiam w tym miejscu, bo do tego wyjaśnienia chcę się odwołać w moim poście o pełnej wyzwalaczu audytu, który znajdziesz tutaj: https://stackoverflow.com/a/43800286/4160788
źródło
Możesz uzyskać listę tabel, które mają liczbę wierszy> 350. Możesz zobaczyć na liście rozwiązań tabela jako wiersz.
źródło
Tylko dlatego, że o tym nie wspomniałem.
Jeśli wersja 2016+, oto kolejna opcja dynamicznego unpivot danych bez faktycznego korzystania z Dynamic SQL.
Przykład
Zwroty
źródło