Jak połączyć tekst z wielu wierszy w jeden ciąg tekstowy w SQL server?

Rozważmy tabelę bazy danych zawierającą nazwy, z trzema wierszami:

Peter
Paul
Mary

Czy jest łatwy sposób na przekształcenie tego w pojedynczy ciąg Peter, Paul, Mary?

Author: Steve Chambers, 2008-10-12

30 answers

Jeśli korzystasz z SQL Server 2017 lub Azure, zobacz Mathieu Renda answer.

Miałem podobny problem, gdy próbowałem połączyć dwa stoły z relacji jeden do wielu. W SQL 2005 odkryłem, że metoda XML PATH bardzo łatwo radzi sobie z konkatenacją wierszy.

Jeśli istnieje tabela o nazwie STUDENTS

SubjectID       StudentName
----------      -------------
1               Mary
1               John
1               Sam
2               Alaina
2               Edward

Oczekiwałem wyniku:

SubjectID       StudentName
----------      -------------
1               Mary, John, Sam
2               Alaina, Edward

Użyłem następującego T-SQL:

SELECT Main.SubjectID,
       LEFT(Main.Students,Len(Main.Students)-1) As "Students"
FROM
    (
        SELECT DISTINCT ST2.SubjectID, 
            (
                SELECT ST1.StudentName + ',' AS [text()]
                FROM dbo.Students ST1
                WHERE ST1.SubjectID = ST2.SubjectID
                ORDER BY ST1.SubjectID
                FOR XML PATH ('')
            ) [Students]
        FROM dbo.Students ST2
    ) [Main]

Można zrobić to samo w bardziej zwarty sposób, jeśli można concat przecinki na początku i użyj substring, aby pominąć pierwszy, więc nie musisz wykonywać pod-zapytania:

SELECT DISTINCT ST2.SubjectID, 
    SUBSTRING(
        (
            SELECT ','+ST1.StudentName  AS [text()]
            FROM dbo.Students ST1
            WHERE ST1.SubjectID = ST2.SubjectID
            ORDER BY ST1.SubjectID
            FOR XML PATH ('')
        ), 2, 1000) [Students]
FROM dbo.Students ST2
 1145
Author: StefanJCollier,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-02 11:20:52

Ta odpowiedź może zwrócić nieoczekiwane wyniki, gdy występuje klauzula ORDER BY. Aby uzyskać spójne wyniki, użyj jednej z metod ścieżki for XML wyszczególnionych w innych odpowiedziach.

Użycie COALESCE:

DECLARE @Names VARCHAR(8000) 
SELECT @Names = COALESCE(@Names + ', ', '') + Name 
FROM People

Tylko jakieś wyjaśnienie (ponieważ ta odpowiedź wydaje się mieć stosunkowo regularne odsłony):

    Coalesce jest tak naprawdę tylko pomocnym oszustwem, które osiąga dwie rzeczy:]}

1) nie ma potrzeby inicjalizacji @Names z pustą wartością łańcuchową.

2) nie ma potrzeby zdejmowania dodatkowego separatora na końcu.

  • powyższe rozwiązanie da nieprawidłowe wyniki, jeśli wiersz ma NULL wartość nazwy (jeśli istnieje NULL , NULL spowoduje @Names NULL Po tym wierszu, a następny wiersz zacznie się od nowa jako pusty łańcuch. Łatwo naprawić za pomocą jednego z dwóch rozwiązań:
DECLARE @Names VARCHAR(8000) 
SELECT @Names = COALESCE(@Names + ', ', '') + Name
FROM People
WHERE Name IS NOT NULL

Lub:

DECLARE @Names VARCHAR(8000) 
SELECT @Names = COALESCE(@Names + ', ', '') + 
    ISNULL(Name, 'N/A')
FROM People

W zależności od zachowania (pierwsza opcja filtruje NULLs out, druga opcja utrzymuje je na liście z Komunikatem znacznika [zamień "N / A" na to, co jest odpowiednie dla Ciebie]).

 908
Author: Chris Shaffer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-30 09:26:56

Jedna metoda jeszcze nie pokazana przez XML data() polecenie w MS SQL Server to:

Przyjmij tabelę nazwaną listą nazw z jedną kolumną nazwaną FName,

SELECT FName + ', ' AS 'data()' 
FROM NameList 
FOR XML PATH('')

Zwraca:

"Peter, Paul, Mary, "

Tylko dodatkowy przecinek musi być rozpatrywany.

Edit: jak przyjęto z komentarza @NReilingh, możesz użyć następującej metody, aby usunąć końcowy przecinek. Zakładając te same nazwy tabeli i kolumn:

STUFF(REPLACE((SELECT '#!' + LTRIM(RTRIM(FName)) AS 'data()' FROM NameList
FOR XML PATH('')),' #!',', '), 1, 2, '') as Brands
 309
Author: jens frandsen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-04-25 15:28:47

In SQL Server 2005

SELECT Stuff(
  (SELECT N', ' + Name FROM Names FOR XML PATH(''),TYPE)
  .value('text()[1]','nvarchar(max)'),1,2,N'')

W SQL Server 2016

Możesz użyć dla składni JSON

Tzn.

SELECT per.ID,
Emails = JSON_VALUE(
   REPLACE(
     (SELECT _ = em.Email FROM Email em WHERE em.Person = per.ID FOR JSON PATH)
    ,'"},{"_":"',', '),'$[0]._'
) 
FROM Person per

I wynik będzie

Id  Emails
1   [email protected]
2   NULL
3   [email protected], [email protected]

To zadziała nawet Twoje dane zawierają nieprawidłowe znaki XML

'"},{"_":"' jest bezpieczny, ponieważ jeśli dane zawierają '"},{"_":"', zostanie on zabezpieczony "},{\"_\":\"

Możesz zastąpić ', ' dowolnym separatorem łańcuchów


I w SQL Server 2017, Azure SQL Baza danych

Możesz użyć nowej funkcji STRING_AGG

 227
Author: Steven Chong,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-23 16:55:05

SQL Server 2017 + i SQL Azure: STRING_AGG

Zaczynając od następnej wersji SQL Server, możemy w końcu łączyć wiersze bez konieczności uciekania się do jakiejkolwiek zmiennej lub XML.

STRING_AGG (Transact-SQL)

Bez grupowania

SELECT STRING_AGG(Name, ', ') AS Departments
FROM HumanResources.Department;

Z grupowaniem:

SELECT GroupName, STRING_AGG(Name, ', ') AS Departments
FROM HumanResources.Department
GROUP BY GroupName;

Z grupowaniem i sortowaniem podrzędnym

SELECT GroupName, STRING_AGG(Name, ', ') WITHIN GROUP (ORDER BY Name ASC) AS Departments
FROM HumanResources.Department 
GROUP BY GroupName;
 194
Author: Mathieu Renda,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-24 05:36:45

W MySQL istnieje funkcja GROUP_CONCAT () , która pozwala na łączenie wartości z wielu wierszy. Przykład:

SELECT 1 AS a, GROUP_CONCAT(name ORDER BY name ASC SEPARATOR ', ') AS people 
FROM users 
WHERE id IN (1,2,3) 
GROUP BY a
 102
Author: Darryl Hein,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-02-26 18:37:58

Użycie COALESCE - dowiedz się więcej tutaj

dla przykładu:

102

103

104

Następnie wpisz poniżej kod w SQL server,

Declare @Numbers AS Nvarchar(MAX) -- It must not be MAX if you have few numbers 
SELECT  @Numbers = COALESCE(@Numbers + ',', '') + Number
FROM   TableName where Number IS NOT NULL

SELECT @Numbers

Wyjście będzie:

102,103,104
 53
Author: pedram,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-09-22 23:27:27

Oracle 11g Release 2 obsługuje funkcję LISTAGG. Dokumentacja Tutaj .

COLUMN employees FORMAT A50

SELECT deptno, LISTAGG(ename, ',') WITHIN GROUP (ORDER BY ename) AS employees
FROM   emp
GROUP BY deptno;

    DEPTNO EMPLOYEES
---------- --------------------------------------------------
        10 CLARK,KING,MILLER
        20 ADAMS,FORD,JONES,SCOTT,SMITH
        30 ALLEN,BLAKE,JAMES,MARTIN,TURNER,WARD

3 rows selected.

Ostrzeżenie

Bądź ostrożny w implementacji tej funkcji, jeśli istnieje możliwość, że wynikowy ciąg znaków przekracza 4000 znaków. To spowoduje wyjątek. Jeśli tak jest, musisz albo obsłużyć wyjątek, albo wywinąć własną funkcję, która zapobiega ciągowi łączącemu przekraczającemu 4000 znaków.

 44
Author: Alex,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-03-14 14:30:15

Tablice Postgres są niesamowite. Przykład:

Utwórz dane testowe:

postgres=# \c test
You are now connected to database "test" as user "hgimenez".
test=# create table names (name text);
CREATE TABLE                                      
test=# insert into names (name) values ('Peter'), ('Paul'), ('Mary');                                                          
INSERT 0 3
test=# select * from names;
 name  
-------
 Peter
 Paul
 Mary
(3 rows)

Połącz je w tablicę:

test=# select array_agg(name) from names;
 array_agg     
------------------- 
 {Peter,Paul,Mary}
(1 row)

Konwertuj tablicę na łańcuch rozdzielany przecinkami:

test=# select array_to_string(array_agg(name), ', ') from names;
 array_to_string
-------------------
 Peter, Paul, Mary
(1 row)

Zrobione

Od PostgreSQL 9.0 jest to jeszcze łatwiejsze.

 43
Author: hgmnz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:18:33

W SQL Server 2005 i nowszych, użyj poniższego zapytania, aby połączyć wiersze.

DECLARE @t table
(
    Id int,
    Name varchar(10)
)
INSERT INTO @t
SELECT 1,'a' UNION ALL
SELECT 1,'b' UNION ALL
SELECT 2,'c' UNION ALL
SELECT 2,'d' 

SELECT ID,
stuff(
(
    SELECT ','+ [Name] FROM @t WHERE Id = t.Id FOR XML PATH('')
),1,1,'') 
FROM (SELECT DISTINCT ID FROM @t ) t
 28
Author: Yogesh Bhadauirya,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-10-20 08:49:30

Nie mam dostępu do serwera SQL w domu, więc domyślam się co do składni tutaj, ale jest mniej więcej:

DECLARE @names VARCHAR(500)

SELECT @names = @names + ' ' + Name
FROM Names
 24
Author: Dana,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-10-12 00:16:20

Zaproponowano rekurencyjne rozwiązanie CTE, ale nie dostarczono kodu. Poniższy kod jest przykładem rekurencyjnego CTE-zauważ, że chociaż wyniki pasują do pytania, dane nie pasują do podanego opisu, ponieważ zakładam, że naprawdę chcesz to robić na grupach wierszy, a nie wszystkich wierszy w tabeli. Zmiana go, aby pasował do wszystkich wierszy w tabeli, jest pozostawiona jako ćwiczenie dla czytelnika.

;with basetable as 
(   SELECT id, CAST(name as varchar(max))name, 
        ROW_NUMBER() OVER(Partition By id     order by seq) rw, 
        COUNT(*) OVER (Partition By id) recs 
FROM (VALUES (1, 'Johnny', 1), (1,'M', 2), 
                  (2,'Bill', 1), (2, 'S.', 4), (2, 'Preston', 5), (2, 'Esq.', 6),
        (3, 'Ted', 1), (3,'Theodore', 2), (3,'Logan', 3),
                  (4, 'Peter', 1), (4,'Paul', 2), (4,'Mary', 3)

           )g(id, name, seq)
),
rCTE as (
    SELECT recs, id, name, rw from basetable where rw=1
    UNION ALL
    SELECT b.recs, r.ID, r.name +', '+ b.name name, r.rw+1
    FROM basetable b
         inner join rCTE r
    on b.id = r.id and b.rw = r.rw+1
)
SELECT name FROM rCTE
WHERE recs = rw and ID=4
 22
Author: jmoreno,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-08-09 21:06:05

Począwszy od PostgreSQL 9.0 jest to dość proste:

select string_agg(name, ',') 
from names;

W wersjach przed 9.0 array_agg() może być używany zgodnie z hgmnz

 22
Author: a_horse_with_no_name,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-10-20 10:42:42

Musisz utworzyć zmienną, która będzie przechowywać wynik końcowy i wybrać do niej, w ten sposób.

Najprostsze Rozwiązanie

DECLARE @char VARCHAR(MAX);

SELECT @char = COALESCE(@char + ', ' + [column], [column]) 
FROM [table];

PRINT @char;
 22
Author: Tigerjz32,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-11-15 21:07:57

W Sql Server vNext będzie to wbudowane w funkcję STRING_AGG, przeczytaj więcej o tym tutaj: https://msdn.microsoft.com/en-us/library/mt790580.aspx

 20
Author: Henrik Fransas,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-01-10 15:42:49

Using XML helped me in getting rows separated with commas. Dla dodatkowego przecinka możemy użyć funkcji replace serwera SQL. Zamiast dodawania przecinka, użycie as' data () ' połączy wiersze ze spacjami, które później można zastąpić przecinkami w składni zapisanej poniżej.

REPLACE(
        (select FName AS 'data()'  from NameList  for xml path(''))
         , ' ', ', ') 
 15
Author: Diwakar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-02-26 18:42:55

Gotowe do użycia rozwiązanie, bez dodatkowych przecinków:

select substring(
        (select ', '+Name AS 'data()' from Names for xml path(''))
       ,3, 255) as "MyList"

Pusta lista spowoduje wartość NULL. Zwykle wstawisz listę do kolumny tabeli lub zmiennej programu: dostosuj maksymalną długość 255 do swoich potrzeb.

(Diwakar i Jens Frandsen dostarczyli dobrych odpowiedzi, ale potrzebują poprawy.)

 14
Author: Daniel Reis,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-02-26 20:03:20
DECLARE @Names VARCHAR(8000)
SELECT @name = ''
SELECT @Names = @Names + ',' + Names FROM People
SELECT SUBSTRING(2, @Names, 7998)

To stawia bezpański przecinek na początku.

Jeśli jednak potrzebujesz innych kolumn lub tabeli potomnej CSV, musisz ją zawinąć w skalarne pole zdefiniowane przez użytkownika (UDF).

Możesz również użyć ścieżki XML jako skorelowanego zapytania podrzędnego w klauzuli SELECT (ale musiałbym poczekać, aż wrócę do pracy, ponieważ Google nie robi rzeczy roboczych w domu: -)

 8
Author: gbn,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-02-26 18:39:58

Z innymi odpowiedziami, osoba czytająca odpowiedź musi być świadoma określonej tabeli domen, takiej jak pojazd lub uczeń. Tabelę należy utworzyć i uzupełnić danymi w celu przetestowania rozwiązania.

Poniżej znajduje się przykład, który używa SQL Server "Information_Schema.Kolumny " tabela. Dzięki temu rozwiązaniu nie trzeba tworzyć tabel ani dodawać danych. Ten przykład tworzy oddzieloną przecinkami listę nazw kolumn dla wszystkich tabel w bazie danych.

SELECT
    Table_Name
    ,STUFF((
        SELECT ',' + Column_Name
        FROM INFORMATION_SCHEMA.Columns Columns
        WHERE Tables.Table_Name = Columns.Table_Name
        ORDER BY Column_Name
        FOR XML PATH ('')), 1, 1, ''
    )Columns
FROM INFORMATION_SCHEMA.Columns Tables
GROUP BY TABLE_NAME 
 8
Author: Mike Barlow - BarDev,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-05-04 19:31:22
SELECT STUFF((SELECT ', ' + name FROM [table] FOR XML PATH('')), 1, 2, '')

Oto przykład:

DECLARE @t TABLE (name VARCHAR(10))
INSERT INTO @t VALUES ('Peter'), ('Paul'), ('Mary')
SELECT STUFF((SELECT ', ' + name FROM @t FOR XML PATH('')), 1, 2, '')
--Peter, Paul, Mary
 7
Author: Max Szczurek,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-28 16:04:05

Dla Oracle DBs, zobacz to pytanie: Jak wiele wierszy może być połączonych w jeden w Oracle bez tworzenia procedury składowanej?

Najlepszą odpowiedzią wydaje się być @Emmanuel, używając wbudowanej funkcji LISTAGG (), dostępnej w Oracle 11g Release 2 i nowszych.

SELECT question_id,
   LISTAGG(element_id, ',') WITHIN GROUP (ORDER BY element_id)
FROM YOUR_TABLE;
GROUP BY question_id

Jak zauważył @user762952 i zgodnie z dokumentacją Oracle http://www.oracle-base.com/articles/misc/string-aggregation-techniques.php , funkcja WM_CONCAT() jest również opcja. Wydaje się stabilny, ale Oracle wyraźnie zaleca używanie go dla dowolnej aplikacji SQL, więc używaj go na własne ryzyko.

Poza tym będziesz musiał napisać własną funkcję; powyższy dokument Oracle zawiera przewodnik, Jak to zrobić.

 6
Author: ZeroK,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:47:36

Aby uniknąć wartości null, możesz użyć CONCAT ()

DECLARE @names VARCHAR(500)
SELECT @names = CONCAT(@names, ' ', name) 
FROM Names
select @names
 5
Author: Rapunzo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-02-12 12:01:27

Ta odpowiedź będzie wymagała pewnych uprawnień na serwerze do działania.

Zespoły są dobrym rozwiązaniem dla Ciebie. Istnieje wiele witryn, które wyjaśniają, jak go utworzyć. Myślę, że bardzo dobrze wyjaśnione jest to jeden

Jeśli chcesz, Mam już utworzony assembly i można pobrać DLL tutaj .

Po pobraniu go, będziesz musiał uruchomić następujący skrypt na serwerze SQL:

CREATE Assembly concat_assembly 
   AUTHORIZATION dbo 
   FROM '<PATH TO Concat.dll IN SERVER>' 
   WITH PERMISSION_SET = SAFE; 
GO 

CREATE AGGREGATE dbo.concat ( 

    @Value NVARCHAR(MAX) 
  , @Delimiter NVARCHAR(4000) 

) RETURNS NVARCHAR(MAX) 
EXTERNAL Name concat_assembly.[Concat.Concat]; 
GO  

sp_configure 'clr enabled', 1;
RECONFIGURE

Zauważ, że ścieżka do montażu może być dostępna dla serwera. Ponieważ pomyślnie wykonałeś wszystkie kroki, możesz użyć funkcji takiej jak:

SELECT dbo.Concat(field1, ',')
FROM Table1
Mam nadzieję, że to pomoże!!!
 5
Author: Nizam,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-05-08 01:39:06

Kompletny przykład MySQL:

Mamy Użytkowników, którzy mogą mieć wiele danych i chcemy mieć wyjście, gdzie możemy zobaczyć wszystkie dane użytkowników na liście:

Wynik:

___________________________
| id   |  rowList         |
|-------------------------|
| 0    | 6, 9             |
| 1    | 1,2,3,4,5,7,8,1  |
|_________________________|

Ustawienie Tabeli:

CREATE TABLE `Data` (
  `id` int(11) NOT NULL,
  `user_id` int(11) NOT NULL
) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=latin1;


INSERT INTO `Data` (`id`, `user_id`) VALUES
(1, 1),
(2, 1),
(3, 1),
(4, 1),
(5, 1),
(6, 0),
(7, 1),
(8, 1),
(9, 0),
(10, 1);


CREATE TABLE `User` (
  `id` int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;


INSERT INTO `User` (`id`) VALUES
(0),
(1);

Query:

SELECT User.id, GROUP_CONCAT(Data.id ORDER BY Data.id) AS rowList FROM User LEFT JOIN Data ON User.id = Data.user_id GROUP BY User.id
 5
Author: user1767754,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-07-22 07:51:12

Bardzo podobała mi się elegancja odpowiedzi Dana. Chciałem go tylko dopełnić.

DECLARE @names VARCHAR(MAX)
SET @names = ''

SELECT @names = @names + ', ' + Name FROM Names 

-- Deleting last two symbols (', ')
SET @sSql = LEFT(@sSql, LEN(@sSql) - 1)
 5
Author: Oleg Sakharov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:55:19

Zwykle używam select w ten sposób do łączenia łańcuchów w SQL Server:

with lines as 
( 
  select 
    row_number() over(order by id) id, -- id is a line id
    line -- line of text.
  from
    source -- line source
), 
result_lines as 
( 
  select 
    id, 
    cast(line as nvarchar(max)) line 
  from 
    lines 
  where 
    id = 1 
  union all 
  select 
    l.id, 
    cast(r.line + N', ' + l.line as nvarchar(max))
  from 
    lines l 
    inner join 
    result_lines r 
    on 
      l.id = r.id + 1 
) 
select top 1 
  line
from
  result_lines
order by
  id desc
 3
Author: Vladimir Nesterovsky,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-07-06 07:06:01

To też może być przydatne

create table #test (id int,name varchar(10))
--use separate inserts on older versions of SQL Server
insert into #test values (1,'Peter'), (1,'Paul'), (1,'Mary'), (2,'Alex'), (3,'Jack')

DECLARE @t VARCHAR(255)
SELECT @t = ISNULL(@t + ',' + name, name) FROM #test WHERE id = 1
select @t
drop table #test

Zwraca

Peter,Paul,Mary
 3
Author: endo64,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-10-25 08:14:23

Jeśli chcesz radzić sobie z nullami, możesz to zrobić dodając klauzulę where lub dodać kolejną KOALESCE wokół pierwszej.

DECLARE @Names VARCHAR(8000) 
SELECT @Names = COALESCE(COALESCE(@Names + ', ', '') + Name, @Names) FROM People
 2
Author: Pramod,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-07-27 20:05:13

W Oracle jest to wm_concat. Wydaje mi się, że ta funkcja jest dostępna w wersji 10g i wyższej.

 2
Author: user762952,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-02-26 18:44:21

--SQL Server 2005 +

CREATE TABLE dbo.Students
(
    StudentId INT
    , Name VARCHAR(50)
    , CONSTRAINT PK_Students PRIMARY KEY (StudentId)
);

CREATE TABLE dbo.Subjects
(
    SubjectId INT
    , Name VARCHAR(50)
    , CONSTRAINT PK_Subjects PRIMARY KEY (SubjectId)
);

CREATE TABLE dbo.Schedules
(
    StudentId INT
    , SubjectId INT
    , CONSTRAINT PK__Schedule PRIMARY KEY (StudentId, SubjectId)
    , CONSTRAINT FK_Schedule_Students FOREIGN KEY (StudentId) REFERENCES dbo.Students (StudentId)
    , CONSTRAINT FK_Schedule_Subjects FOREIGN KEY (SubjectId) REFERENCES dbo.Subjects (SubjectId)
);

INSERT dbo.Students (StudentId, Name) VALUES
    (1, 'Mary')
    , (2, 'John')
    , (3, 'Sam')
    , (4, 'Alaina')
    , (5, 'Edward')
;

INSERT dbo.Subjects (SubjectId, Name) VALUES
    (1, 'Physics')
    , (2, 'Geography')
    , (3, 'French')
    , (4, 'Gymnastics')
;

INSERT dbo.Schedules (StudentId, SubjectId) VALUES
    (1, 1)      --Mary, Physics
    , (2, 1)    --John, Physics
    , (3, 1)    --Sam, Physics
    , (4, 2)    --Alaina, Geography
    , (5, 2)    --Edward, Geography
;

SELECT 
    sub.SubjectId
    , sub.Name AS [SubjectName]
    , ISNULL( x.Students, '') AS Students
FROM
    dbo.Subjects sub
    OUTER APPLY
    (
        SELECT 
            CASE ROW_NUMBER() OVER (ORDER BY stu.Name) WHEN 1 THEN '' ELSE ', ' END
            + stu.Name
        FROM
            dbo.Students stu
            INNER JOIN dbo.Schedules sch
                ON stu.StudentId = sch.StudentId
        WHERE
            sch.SubjectId = sub.SubjectId
        ORDER BY
            stu.Name
        FOR XML PATH('')
    ) x (Students)
;
 2
Author: Graeme,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-01 20:42:40