Rozważmy tabelę bazy danych zawierającą nazwy z trzema wierszami:
Peter
Paul
Mary
Czy istnieje prosty sposób, aby zmienić to w pojedynczy ciąg Peter, Paul, Mary
?
Rozważmy tabelę bazy danych zawierającą nazwy z trzema wierszami:
Peter
Paul
Mary
Czy istnieje prosty sposób, aby zmienić to w pojedynczy ciąg Peter, Paul, Mary
?
Odpowiedzi:
Jeśli korzystasz z SQL Server 2017 lub Azure, zobacz odpowiedź Mathieu Renda .
Miałem podobny problem, kiedy próbowałem połączyć dwie tabele z relacjami jeden do wielu. W SQL 2005 odkryłem, że ta
XML PATH
metoda bardzo łatwo radzi sobie z konkatenacją wierszy.Jeśli istnieje tabela o nazwie
STUDENTS
Spodziewałem się wyniku:
Użyłem następujących
T-SQL
:Możesz zrobić to samo w bardziej zwarty sposób, jeśli możesz przeciąć przecinki na początku i użyć,
substring
aby pominąć pierwszy, aby nie trzeba było wykonywać zapytania podrzędnego:źródło
<
lub&
. Zobacz komentarz @ BenHinman.FOR XML PATH ('')
. Oznacza to, że nie należy jej uważać za niezawodną, ponieważ jakakolwiek łatka lub aktualizacja może zmienić sposób jej działania. Zasadniczo polega na przestarzałej funkcji.FOR XML
aby generować XML, a nie łączyć dowolne ciągi. Dlatego ucieka&
,<
a>
do kodów jednostki XML (&
,<
,>
). Zakładam, że również będzie uciec"
i'
do"
oraz'
w atrybutach, jak również. To nieGROUP_CONCAT()
,string_agg()
,array_agg()
,listagg()
, itd., Nawet jeśli można zrobić to niby zrobić. My powinniśmy spędzać nasz czas wymagający Microsoft wdrożyć właściwą funkcję.string_agg
w v.Next. i wszystko to może zniknąć.Użyj
COALESCE
:Tylko wyjaśnienie (ponieważ ta odpowiedź wydaje się mieć stosunkowo regularne wyświetlenia):
1) Nie ma potrzeby inicjowania
@Names
z pustą wartością ciągu.2) Nie trzeba zdejmować dodatkowego separatora na końcu.
@Names
NULL po tym wierszu, a następny wiersz zacznie od nowa jako pusty ciąg znaków. Łatwo naprawiony za pomocą jednego z dwóch rozwiązania:lub:
W zależności od tego, jakie zachowanie chcesz (pierwsza opcja po prostu odfiltrowuje wartości NULL , druga opcja utrzymuje je na liście z komunikatem znacznika [zamień „nie dotyczy” na to, co jest odpowiednie dla ciebie).
źródło
SQL Server 2017+ i SQL Azure: STRING_AGG
Począwszy od kolejnej wersji programu SQL Server, możemy w końcu łączyć wiersze bez konieczności uciekania się do jakiejkolwiek zmiennej lub czarów XML.
STRING_AGG (Transact-SQL)
Bez grupowania
Z grupowaniem:
Z grupowaniem i sortowaniem
źródło
Jedną z metod, których jeszcze nie pokazano za pomocą
XML
data()
polecenia w MS SQL Server, jest:Załóżmy tabelę o nazwie NameList z jedną kolumną o nazwie FName,
zwroty:
Należy uwzględnić tylko dodatkowy przecinek.
Edycja: Zgodnie z komentarzem @ NReilingh możesz użyć następującej metody, aby usunąć przecinek końcowy. Zakładając tę samą nazwę tabeli i kolumny:
źródło
+ ', '
, nadal dodaje pojedynczą spację między każdym połączonym elementem.SELECT STUFF(REPLACE((SELECT '#!'+city AS 'data()' FROM #cityzip FOR XML PATH ('')),' #!',', '),1,2,'')
W SQL Server 2005
W SQL Server 2016
możesz użyć składni FOR JSON
to znaczy
I wynik się stanie
Działa to nawet twoje dane zawierają nieprawidłowe znaki XML
'"},{"_":"'
jest bezpieczne, ponieważ jeśli wy zawierać dane'"},{"_":"',
będzie uciekł"},{\"_\":\"
Możesz zastąpić
', '
dowolnym separatorem ciągówW SQL Server 2017 baza danych SQL Azure
Możesz użyć nowej funkcji STRING_AGG
źródło
<
,>
,&
, itd., KtóreFOR XML PATH('')
będą automatycznie uciec.W MySQL znajduje się funkcja GROUP_CONCAT () , która pozwala łączyć wartości z wielu wierszy. Przykład:
źródło
SEPARATOR '", "'
, przegapię kilka znaków na końcu ostatniego wpisu. dlaczego to się może zdarzyć?CHAR
, musisz rzucić ją, np. PrzezGROUP_CONCAT( CAST(id AS CHAR(8)) ORDER BY id ASC SEPARATOR ',')
2), jeśli masz wiele wartości, powinieneś zwiększyćgroup_concat_max_len
jak napisano w stackoverflow.com/a/1278210/1498405Użyj COALESCE - dowiedz się więcej tutaj
Dla przykładu:
Następnie wpisz poniższy kod na serwerze SQL,
Dane wyjściowe byłyby:
źródło
Declare @Numbers AS Nvarchar(MAX)
i działało dobrze. Czy możesz wyjaśnić, dlaczego nie zaleca się jego używania?Tablice Postgres są niesamowite. Przykład:
Utwórz dane testowe:
Agreguj je w tablicy:
Konwertuj tablicę na ciąg rozdzielany przecinkami:
GOTOWY
Od PostgreSQL 9.0 jest jeszcze łatwiejszy .
źródło
select array_to_string(array_agg(name||'('||id||')'
Oracle 11g Release 2 obsługuje funkcję LISTAGG. Dokumentacja tutaj .
Ostrzeżenie
Zachowaj ostrożność przy wdrażaniu tej funkcji, jeśli istnieje możliwość, że wynikowy ciąg przekroczy ponad 4000 znaków. Wyrzuci wyjątek. W takim przypadku musisz obsłużyć wyjątek lub uruchomić własną funkcję, która zapobiega łączeniu ciągu przekraczającego 4000 znaków.
źródło
LISTAGG
działa idealnie! Po prostu przeczytaj dokument podlinkowany tutaj.wm_concat
usunięto z wersji 12c i wyższych.W SQL Server 2005 i nowszych wersjach użyj poniższego zapytania, aby połączyć wiersze.
źródło
<
lub&
.Nie mam dostępu do SQL Server w domu, więc zgaduję tutaj o składni, ale mniej więcej:
źródło
SELECT @names = @names + CASE WHEN LEN(@names)=0 THEN '' ELSE ' ' END + Name FROM Names
SELECT @names = @names + ISNULL(' ' + Name, '')
Zaproponowano rekurencyjne rozwiązanie CTE, ale nie podano kodu. Poniższy kod jest przykładem rekurencyjnego CTE. Zauważ, że chociaż wyniki pasują do pytania, dane nie do końca pasują do podanego opisu, ponieważ zakładam, że naprawdę chcesz to robić w grupach wierszy, a nie we wszystkich wierszach w tabeli. Zmiana go tak, aby pasowała do wszystkich wierszy w tabeli, pozostaje dla czytelnika ćwiczeniem.
źródło
name
kolumnę do łańcucha oddzielony przecinkami na 4 grupy oid
s. Na pierwszy rzut oka myślę, że to więcej pracy niż większość innych rozwiązań dla SQL Server.Musisz stworzyć zmienną, która będzie utrzymywać twój końcowy wynik i wybrać do niego, tak jak to.
Najłatwiejsze rozwiązanie
źródło
Począwszy od PostgreSQL 9.0 jest to dość proste:
W wersjach wcześniejszych niż 9.0
array_agg()
można używać, jak pokazuje hgmnzźródło
SELECT string_agg(non_text_type::text, ',') FROM table
varchar
lubchar
W SQL Server vNext będzie to wbudowane w funkcję STRING_AGG, czytaj więcej na ten temat tutaj: https://msdn.microsoft.com/en-us/library/mt790580.aspx
źródło
Korzystanie z XML pomogło mi w oddzieleniu wierszy przecinkami. Za dodatkowy przecinek możemy użyć funkcji zamiany programu SQL Server. Zamiast dodawać przecinek, użycie AS 'data ()' połączy wiersze ze spacjami, które później można zastąpić przecinkami zgodnie ze składnią zapisaną poniżej.
źródło
Gotowe do użycia rozwiązanie bez dodatkowych przecinków:
Pusta lista spowoduje wartość NULL. Zazwyczaj wstawiasz listę do kolumny tabeli lub zmiennej programu: dostosuj maksymalną długość 255 do swoich potrzeb.
(Diwakar i Jens Frandsen udzielili dobrych odpowiedzi, ale wymagają poprawy.)
źródło
', '
ze','
jeśli nie chcesz dodatkową przestrzeń.Oto próbka:
źródło
To stawia bezpański przecinek na początku.
Jeśli jednak potrzebujesz innych kolumn lub CSV tabeli podrzędnej, musisz zawinąć ją w skalarne pole zdefiniowane przez użytkownika (UDF).
Możesz użyć ścieżki XML jako skorelowanego podkwerendy również w klauzuli SELECT (ale musiałbym poczekać, aż wrócę do pracy, ponieważ Google nie wykonuje pracy w domu :-)
źródło
Przy innych odpowiedziach osoba czytająca odpowiedź musi być świadoma konkretnej tabeli domen, takiej jak pojazd lub uczeń. Tabela musi zostać utworzona i wypełniona danymi, aby przetestować rozwiązanie.
Poniżej znajduje się przykład wykorzystujący tabelę „Information_Schema.Columns” programu SQL Server. Korzystając z tego rozwiązania, nie trzeba tworzyć tabel ani dodawać danych. Ten przykład tworzy listę nazw kolumn oddzieloną przecinkami dla wszystkich tabel w bazie danych.
źródło
W przypadku baz danych Oracle zobacz to pytanie: Jak można połączyć wiele wierszy w jeden w Oracle bez tworzenia procedury składowanej?
Najlepszą odpowiedzią wydaje się być @Emmanuel, wykorzystujący wbudowaną funkcję LISTAGG (), dostępną w Oracle 11g Release 2 i późniejszych.
jak wskazał @ user762952 i zgodnie z dokumentacją Oracle http://www.oracle-base.com/articles/misc/string-aggregation-techniques.php , funkcja WM_CONCAT () jest również opcją. Wydaje się stabilny, ale Oracle wyraźnie odradza używanie go do dowolnej aplikacji SQL, więc używaj na własne ryzyko.
Poza tym będziesz musiał napisać własną funkcję; powyższy dokument Oracle zawiera przewodnik, jak to zrobić.
źródło
Aby uniknąć wartości pustych, możesz użyć CONCAT ()
źródło
Naprawdę podobała mi się elegancja odpowiedzi Dany . Chciałem tylko, żeby był kompletny.
źródło
SELECT @names = @names + CASE WHEN LEN(@names)=0 THEN '' ELSE ', ' END + Name FROM Names
nie trzeba było go później obcinać.Ta odpowiedź wymaga pewnych uprawnień na serwerze do pracy.
Zespoły są dla Ciebie dobrą opcją. Istnieje wiele witryn, które wyjaśniają, jak je utworzyć. Ten, moim zdaniem jest bardzo dobrze wyjaśnione jest to jeden
Jeśli chcesz, utworzyłem już zespół i możliwe jest pobranie biblioteki DLL tutaj .
Po pobraniu konieczne będzie uruchomienie następującego skryptu na serwerze SQL:
Zauważ, że ścieżka do zestawu może być dostępna dla serwera. Ponieważ pomyślnie wykonałeś wszystkie kroki, możesz użyć funkcji takiej jak:
Mam nadzieję, że to pomoże!!!
źródło
Kompletny MySQL Przykład:
Mamy użytkowników, którzy mogą mieć wiele danych i chcemy mieć dane wyjściowe, w których możemy zobaczyć dane wszystkich użytkowników na liście:
Wynik:
Konfiguracja stołu:
Pytanie:
źródło
Zazwyczaj używam takiego wyboru do łączenia łańcuchów w SQL Server:
źródło
Jeśli chcesz poradzić sobie z zerami, możesz to zrobić, dodając klauzulę where lub dodając kolejną wartość COALESCE wokół pierwszej.
źródło
To zadziałało dla mnie ( SqlServer 2016 ):
Oto źródło: https://www.mytecbits.com/
I rozwiązanie dla MySql (ponieważ ta strona pojawia się w Google dla MySql)
Z dokumentacji MySql
źródło
Tak jest w Oracle
wm_concat
. Wierzę, że ta funkcja jest dostępna w wersji 10 g i wyższej.źródło
To też może być przydatne
zwroty
źródło