Czy byłoby możliwe skonstruowanie kodu SQL w celu konkatenacji wartości kolumn z wielu wierszy?
Oto przykład:
Tabela A
PID ZA b do
Tabela B.
PID SEQ Desc A 1 mieć A 2 miło 3 dni. B 1 Dobra robota. C 1 Tak C 2 możemy C 3 zrobić C 4 ta praca!
Wynik SQL powinien być -
PID Desc Miłego dnia. B Dobra robota. C Tak, możemy wykonać tę pracę!
Więc w zasadzie kolumna Opis dla tabeli wyjściowej jest konkatenacją wartości SEQ z tabeli B?
Jakaś pomoc dotycząca SQL?
sql
oracle
string-aggregation
jagamot
źródło
źródło
Odpowiedzi:
Istnieje kilka sposobów w zależności od posiadanej wersji - zapoznaj się z dokumentacją Oracle dotyczącą technik agregacji ciągów . Bardzo często używa się
LISTAGG
:Następnie dołącz do,
A
aby wybrać,pids
co chcesz.Uwaga: po wyjęciu z pudełka
LISTAGG
działa poprawnie tylko zVARCHAR2
kolumnami.źródło
Istnieje również
XMLAGG
funkcja, która działa w wersjach wcześniejszych niż 11.2. PonieważWM_CONCAT
jest nieudokumentowany i nie jest obsługiwany przez Oracle , zaleca się, aby nie używać go w systemie produkcyjnym.Za pomocą
XMLAGG
możesz wykonać następujące czynności:Co to robi
ename
kolumny (połączone przecinkiem) zemployee_names
tabeli w elemencie xml (z tagiem E)źródło
Z klauzulą modelu SQL:
Pisałem o tym tutaj . A jeśli klikniesz link do wątku OTN, znajdziesz więcej, w tym porównanie wydajności.
źródło
Funkcja analityczna LISTAGG została wprowadzona w Oracle 11g Release 2 , co bardzo ułatwia agregację ciągów. Jeśli używasz 11g Release 2, powinieneś użyć tej funkcji do agregacji ciągów. Więcej informacji na temat konkatenacji ciągów można znaleźć poniżej adresu URL.
http://www.oracle-base.com/articles/misc/StringAggregationTechniques.php
Konkatenacja ciągów
źródło
Jak sugeruje większość odpowiedzi,
LISTAGG
jest to opcja oczywista. Jednak jednym irytującym aspektemLISTAGG
jest to, że jeśli całkowita długość łączonego ciągu przekracza 4000 znaków (limit dlaVARCHAR2
SQL), generowany jest poniższy błąd, który jest trudny do zarządzania w wersjach Oracle do 12.1Nową funkcją dodaną w 12cR2 jest
ON OVERFLOW
klauzulaLISTAGG
. Zapytanie zawierające tę klauzulę wyglądałoby następująco:Powyższe ograniczy wynik do 4000 znaków, ale nie spowoduje zgłoszenia
ORA-01489
błędu.Oto niektóre z dodatkowych opcji
ON OVERFLOW
klauzuli:ON OVERFLOW TRUNCATE 'Contd..'
: Wyświetli się'Contd..'
na końcu ciągu (domyślnie...
)ON OVERFLOW TRUNCATE ''
: Spowoduje to wyświetlenie 4000 znaków bez żadnego łańcucha kończącego.ON OVERFLOW TRUNCATE WITH COUNT
: Wyświetli całkowitą liczbę znaków na końcu po znakach kończących. Np .: - '...(5512)
'ON OVERFLOW ERROR
: Jeśli spodziewaszLISTAGG
się, żeORA-01489
błąd zakończy się niepowodzeniem (co i tak jest domyślne).źródło
Dla tych, którzy muszą rozwiązać ten problem za pomocą Oracle 9i (lub wcześniejszej), prawdopodobnie będziesz musiał użyć SYS_CONNECT_BY_PATH, ponieważ LISTAGG nie jest dostępny.
Aby odpowiedzieć na OP, następujące zapytanie wyświetli PID z tabeli A i połączy wszystkie kolumny DESC z tabeli B:
Mogą również istnieć przypadki, w których wszystkie klucze i wartości są zawarte w jednej tabeli. Poniższego zapytania można użyć, gdy nie ma tabeli A i istnieje tylko tabela B:
Wszystkie wartości można dowolnie zmienić. Poszczególne konkatenowane opisy można zmienić w klauzuli PARTITION BY, a listę PID można zmienić w ostatecznej klauzuli ORDER BY.
Alternatywnie: może się zdarzyć, że będziesz chciał połączyć wszystkie wartości z całej tabeli w jeden wiersz.
Kluczową ideą jest tutaj użycie sztucznej wartości dla grupy opisów, które mają być łączone.
W poniższym zapytaniu zostanie użyty stały ciąg „1”, ale każda wartość będzie działać:
Poszczególne połączone opisy można zmienić w klauzuli PARTITION BY.
Kilka innych odpowiedzi na tej stronie również wspomniało o tym niezwykle pomocnym źródle: https://oracle-base.com/articles/misc/string-aggregation-techniques
źródło
LISTAGG zapewnia najlepszą wydajność, jeśli sortowanie jest koniecznością (00: 00: 05.85)
SELECT pid, LISTAGG(Desc, ' ') WITHIN GROUP (ORDER BY seq) AS description FROM B GROUP BY pid;
COLLECT zapewnia najlepszą wydajność, jeśli sortowanie nie jest potrzebne (00: 00: 02.90):
SELECT pid, TO_STRING(CAST(COLLECT(Desc) AS varchar2_ntt)) AS Vals FROM B GROUP BY pid;
ZBIERZ przy zamawianiu jest nieco wolniejszy (00: 00: 07.08):
SELECT pid, TO_STRING(CAST(COLLECT(Desc ORDER BY Desc) AS varchar2_ntt)) AS Vals FROM B GROUP BY pid;
Wszystkie inne techniki były wolniejsze.
źródło
Przed uruchomieniem zapytania wybierającego uruchom to:
SET SERVEROUT ON SIZE 6000
źródło
Wypróbuj ten kod:
źródło
W zaznacz, gdzie chcesz umieścić konkatenację, wywołaj funkcję SQL.
Na przykład:
Następnie dla funkcji SQL:
Składnia nagłówka funkcji może być nieprawidłowa, ale zasada działa.
źródło