45 Pertanyaan: Bagaimana menggabungkan teks dari beberapa baris menjadi satu string teks dalam SQL server?

pertanyaan dibuat di Mon, Feb 19, 2018 12:00 AM

Pertimbangkan tabel database yang menyimpan nama, dengan tiga baris:

 
Peter
Paul
Mary

Apakah ada cara mudah untuk mengubahnya menjadi satu string Peter, Paul, Mary?

    
1720
  1. Untuk jawaban khusus untuk SQL Server, coba pertanyaan ini .
    2008-10-12 00: 03: 42Z
  2. Untuk MySQL, periksa Group_Concat dari jawaban ini
    2011-05-06 19: 48: 02Z
  3. Saya berharap versi SQL Server berikutnya akan menawarkan fitur baru untuk menyelesaikan multi-row string concatination secara elegan tanpa kekonyolan FOR XML PATH.
    2014-10-02 11: 47: 17Z
  4. Bukan SQL, tetapi jika ini adalah hal yang hanya sekali, Anda dapat menempelkan daftar ke dalam alat di dalam browser ini convert.town/column-to-comma-separated-list
    2015-05-27 07: 56: 14Z
  5. Di Oracle Anda dapat menggunakan LISTAGG (COLUMN_NAME) dari 11g r2 sebelum ada fungsi yang tidak didukung bernama WM_CONCAT (COLUMN_NAME) yang melakukan hal yang sama.
    2017-07-06 06: 32: 06Z
30 Jawaban                              30                         

Jika Anda menggunakan SQL Server 2017 atau Azure, lihat Mathieu Renda jawab .

Saya memiliki masalah serupa ketika saya mencoba untuk bergabung dengan dua tabel dengan hubungan satu-ke-banyak. Di SQL 2005 saya menemukan bahwa metode XML PATH dapat menangani penggabungan baris dengan sangat mudah. ​​

Jika ada tabel bernama STUDENTS

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

Hasil yang saya harapkan adalah:

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

Saya menggunakan T-SQL berikut:

 
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]

Anda dapat melakukan hal yang sama dengan cara yang lebih ringkas jika Anda dapat membuat tanda koma di awal dan menggunakan substring untuk melewati yang pertama sehingga Anda tidak perlu melakukan sub-permintaan:

 
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
    
1275
2018-08-02 11: 20: 52Z
  1. Solusi yang bagus. Berikut ini mungkin bermanfaat jika Anda perlu menangani karakter khusus seperti yang ada di HTML: Rob Farley: Menangani karakter khusus dengan UNTUK XML PATH ('') .
    2013-04-17 12: 35: 18Z
  2. Tampaknya ini tidak berfungsi jika nama-nama tersebut mengandung karakter XML seperti < atau &. Lihat @ BenHinman komentar.
    2013-08-13 01: 26: 59Z
  3. NB: Metode ini bergantung pada perilaku tidak terdokumentasi dari FOR XML PATH (''). Itu berarti itu tidak boleh dianggap andal karena setiap patch atau pembaruan dapat mengubah cara kerjanya. Ini pada dasarnya mengandalkan fitur yang sudah usang.
    2014-11-13 18: 54: 02Z
  4. @ Whelkaholism Intinya adalah bahwa FOR XML dimaksudkan untuk menghasilkan XML, bukan merangkai string acak. Itu sebabnya ia lolos dari &, < dan > ke kode entitas XML (&amp;, &lt;, &gt;). Saya menganggap itu juga akan lolos " dan ' ke &quot; dan &apos; dalam atribut juga. Ini bukan GROUP_CONCAT(), string_agg(), array_agg(), listagg(), dll. Bahkan jika Anda bisa membuatnya melakukannya. Kami seharusnya menghabiskan waktu kami menuntut Microsoft menerapkan fungsi yang tepat.
    2015-03-23 ​​14: 15: 21Z
  5. Berita baik: MS SQL Server akan menambahkan string_agg di v.Next. dan semua ini bisa hilang.
    2017-04-06 00: 32: 48Z
  

Jawaban ini dapat mengembalikan hasil yang tidak terduga Untuk hasil yang konsisten, gunakan salah satu metode UNTUK XML PATH yang dirinci dalam jawaban lain.

Gunakan COALESCE:

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

Hanya beberapa penjelasan (karena jawaban ini tampaknya mendapatkan tampilan yang relatif teratur):

  • Coalesce sebenarnya hanya cheat bermanfaat yang menyelesaikan dua hal:

1) Tidak perlu menginisialisasi @Names dengan nilai string kosong.

2) Tidak perlu melepas pemisah tambahan di akhir.

  • Solusi di atas akan memberikan hasil yang salah jika sebuah baris memiliki nilai nama NULL (jika ada NULL , NULL akan membuat @Names NULL setelah baris itu, dan baris berikutnya akan memulai kembali sebagai string kosong lagi. Mudah diperbaiki dengan salah satu dari dua solusi:
 
DECLARE @Names VARCHAR(8000) 
SELECT @Names = COALESCE(@Names + ', ', '') + Name
FROM People
WHERE Name IS NOT NULL

atau:

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

Bergantung pada perilaku apa yang Anda inginkan (opsi pertama hanya menyaring NULL , opsi kedua menyimpannya dalam daftar dengan pesan penanda [ganti 'N /A' dengan apa pun yang sesuai untuk Anda]).

    
955
2019-04-30 12: 02: 01Z
  1. Agar jelas, penggabungan tidak ada hubungannya dengan membuat daftar, itu hanya memastikan bahwa nilai NULL tidak termasuk.
    2009-02-13 12: 02: 46Z
  2. @ Graeme Perrow Tidak mengecualikan nilai NULL (a WHERE diperlukan untuk itu - ini akan kehilangan hasil jika salah satu input nilai adalah NULL), dan itu diperlukan dalam pendekatan ini karena: NULL + non-NULL - > NULL dan non-NULL + NULL - > BATAL; @Name juga NULL secara default dan, pada kenyataannya, properti itu digunakan sebagai sentinel implisit di sini untuk menentukan apakah ',' harus ditambahkan atau tidak.
    2010-08-15 18: 57: 57Z
  3. Harap dicatat bahwa metode penggabungan ini bergantung pada SQL Server yang mengeksekusi kueri dengan rencana tertentu. Saya telah kedapatan menggunakan metode ini (dengan tambahan ORDER BY). Ketika berhadapan dengan sejumlah kecil baris itu berfungsi dengan baik tetapi dengan lebih banyak data SQL Server memilih rencana yang berbeda yang mengakibatkan memilih item pertama tanpa penggabungan apa pun. Lihat artikel ini oleh Anith Sen.
    2012-04-26 02: 18: 01Z
  4. Metode ini tidak dapat digunakan sebagai sub kueri dalam daftar pilih atau di mana-klausa, karena ini menggunakan variabel tSQL. Dalam kasus seperti itu, Anda dapat menggunakan metode yang ditawarkan oleh @Ritesh
    2013-08-02 08: 10: 54Z
  5. Ini bukan metode penggabungan yang andal. Itu tidak didukung dan tidak boleh digunakan (per Microsoft, mis. support.microsoft.com/en -us /kb /287515 , connect.microsoft.com/SQLServer/Feedback /Detail /704389 ). Itu bisa berubah tanpa peringatan. Gunakan teknik PATH XML yang dibahas dalam stackoverflow.com/questions/5031204/... Saya menulis lebih banyak di sini: marc.durdin.net/2015/07/07 ...
    2015-07-15 00: 23: 20Z

Salah satu metode yang belum ditampilkan melalui perintah XML data() di MS SQL Server adalah:

Asumsikan tabel bernama NameList dengan satu kolom bernama FName,

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

kembali:

 
"Peter, Paul, Mary, "

Hanya koma ekstra yang harus ditangani.

Edit: Sebagaimana diadopsi dari komentar @ NReilingh, Anda dapat menggunakan metode berikut untuk menghapus koma tertinggal. Dengan asumsi nama tabel dan kolom yang sama:

 
STUFF(REPLACE((SELECT '#!' + LTRIM(RTRIM(FName)) AS 'data()' FROM NameList
FOR XML PATH('')),' #!',', '), 1, 2, '') as Brands
    
336
2016-04-25 15: 28: 47Z
  1. holy s ** t itu luar biasa! Ketika dieksekusi sendiri, seperti dalam contoh Anda hasilnya diformat sebagai hyperlink, bahwa ketika diklik (dalam SSMS) membuka jendela baru yang berisi data, tetapi ketika digunakan sebagai bagian dari kueri yang lebih besar itu hanya muncul sebagai string. Apakah ini sebuah string? atau apakah xml yang perlu saya perlakukan berbeda dalam aplikasi yang akan menggunakan data ini?
    2012-09-07 15: 56: 00Z
  2. Pendekatan ini juga XML-lolos karakter seperti < dan &gt ;. Jadi, PILIH '< b >' + FName + '< /b >' menghasilkan "& lt; b & gt; John & lt; /b & gt; & lt; b & gt; Paul ..."
    2014-02-26 18: 34: 07Z
  3. Solusi rapi. Saya memperhatikan bahwa meskipun saya tidak menambahkan + ', ', ia masih menambahkan satu ruang di antara setiap elemen yang disatukan.
    2014-10-03 22: 40: 38Z
  4. @ Baodad Itu tampaknya menjadi bagian dari kesepakatan. Anda dapat mengatasinya dengan mengganti karakter token yang ditambahkan. Misalnya, ini melakukan daftar yang dibatasi koma sempurna untuk panjang apa pun: SELECT STUFF(REPLACE((SELECT '#!'+city AS 'data()' FROM #cityzip FOR XML PATH ('')),' #!',', '),1,2,'')
    2016-02-29 18: 12: 13Z
  5. Wow, sebenarnya dalam pengujian saya menggunakan data () dan penggantinya adalah WAY yang lebih berkinerja daripada tidak. Sangat aneh.
    2016-02-29 18: 33: 08Z

SQL Server 2017+ dan SQL Azure: STRING_AGG

Dimulai dengan versi SQL Server berikutnya, kita akhirnya dapat menyatukan seluruh baris tanpa harus menggunakan variabel apa pun atau sihir XML.

STRING_AGG (Transact-SQL)

Tanpa pengelompokan

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

Dengan pengelompokan:

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

Dengan pengelompokan dan sub-sortasi

 
SELECT GroupName, STRING_AGG(Name, ', ') WITHIN GROUP (ORDER BY Name ASC) AS Departments
FROM HumanResources.Department 
GROUP BY GroupName;
    
300
2018-07-24 05: 36: 45Z
  1. Dan, tidak seperti solusi CLR, Anda memiliki kendali atas penyortiran.
    2017-07-10 16: 17: 06Z
  2. Ini bekerja dengan SQL Azure. Jawaban bagus!
    2017-10-11 20: 27: 04Z
  3. Ini juga bekerja untuk saya dalam Azure SQL. Cemerlang!
    2018-01-04 20: 31: 41Z

Di SQL Server 2005

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

Di SQL Server 2016

Anda dapat menggunakan UNTUK sintaks JSON

yaitu

 
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

Dan hasilnya akan menjadi

 
Id  Emails
1   abc@gmail.com
2   NULL
3   def@gmail.com, xyz@gmail.com

Ini akan berfungsi bahkan data Anda mengandung karakter XML yang tidak valid

'"},{"_":"' aman karena jika data Anda mengandung '"},{"_":"', itu akan lolos ke "},{\"_\":\"

Anda dapat mengganti ', ' dengan pemisah string apa pun


Dan di SQL Server 2017, Azure SQL Database

Anda dapat menggunakan STRING_AGG baru fungsi

    
270
2018-07-23 16: 55: 05Z
  1. Penggunaan fungsi STUFF dengan baik untuk mem-nix dua karakter utama.
    2011-08-11 23: 12: 59Z
  2. Saya paling suka solusi ini, karena saya dapat dengan mudah menggunakannya dalam daftar pilih dengan menambahkan 'sebagai < label >'. Saya tidak yakin bagaimana melakukan ini dengan solusi @Ritesh.
    2013-08-02 08: 27: 52Z
  3. Ini lebih baik daripada jawaban yang diterima karena opsi ini juga menangani un-escaping XML reserverd karakter seperti <, >, &, dll. yang FOR XML PATH('') akan otomatis lolos.
    2014-04-07 21: 35: 21Z
  4. Ini adalah respons yang luar biasa karena menyelesaikan masalah dan menyediakan cara terbaik untuk melakukan hal-hal dalam versi SQL yang berbeda sekarang saya berharap saya bisa menggunakan 2017 /Azure
    2018-05-21 14: 27: 54Z

Di MySQL ada fungsi, GROUP_CONCAT () , yang memungkinkan Anda menggabungkan nilai dari beberapa baris. Contoh:

 
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
    
112
2012-02-26 18: 37: 58Z
  1. Dulu suka yang ini, belum melihat alternatif untuk fungsi ini dengan Db lain!
    2009-06-18 06: 05: 30Z
  2. Ini benar-benar menyelesaikan masalah saya. Saya mencoba untuk menarik semua tanggal pembayaran untuk biaya yang diberikan pada akun, ini menyelesaikannya dengan sempurna. Terima kasih!
    2016-08-26 15: 47: 45Z
  3. berfungsi dengan baik. Tetapi ketika saya menggunakan SEPARATOR '", "' saya akan kehilangan beberapa karakter di akhir entri terakhir. mengapa ini bisa terjadi?
    2016-11-27 13: 05: 59Z
  4. @ gooleem Saya tidak jelas tentang apa yang Anda maksud, tetapi fungsi ini hanya menempatkan pemisah antara item, bukan setelah. Jika itu bukan jawabannya, saya sarankan memposting pertanyaan baru.
    2016-12-04 23: 41: 35Z
  5. @ DarrylHein untuk kebutuhan saya, saya menggunakan pemisah seperti di atas. Tapi ini memotong saya beberapa karakter di akhir output. Ini sangat aneh dan sepertinya bug. Saya tidak punya solusi, saya baru saja menyelesaikannya.
    2016-12-06 09: 28: 00Z

Gunakan COALESCE - Pelajari lebih lanjut dari sini

Sebagai contoh:

  

102

     

103

     

104

Kemudian tulis kode di bawah ini dalam 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

Outputnya adalah:

 
102,103,104
    
54
2017-09-22 23: 27: 27Z
  1. Inis benar-benar solusi IMO terbaik karena menghindari masalah penyandian yang hadir untuk XML. Saya menggunakan Declare @Numbers AS Nvarchar(MAX) dan bekerja dengan baik. Bisakah Anda jelaskan mengapa Anda merekomendasikan untuk tidak menggunakannya?
    2016-08-03 15: 01: 16Z
  2. Solusi ini telah diposting 8 tahun yang lalu! stackoverflow.com/a/194887/986862
    2017-05-03 21: 53: 44Z
  3. Mengapa kueri ini kembali ??? simbol bukan yang Cyrillic? Apakah ini masalah keluaran saja?
    2017-12-07 11: 31: 13Z

Array Postgres mengagumkan. Contoh:

Buat beberapa data uji:

 
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)

Gabungkan mereka dalam sebuah array:

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

Konversikan array menjadi string yang dibatasi koma:

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

DIBUAT

Sejak PostgreSQL 9.0, itu adalah lebih mudah .

    
47
2017-05-23 12: 18: 33Z
  1. Jika Anda membutuhkan lebih dari satu kolom, misalnya id karyawan mereka dalam kurung menggunakan operator concat: select array_to_string(array_agg(name||'('||id||')'
    2015-02-27 11: 50: 37Z
  2. Tidak berlaku untuk sql-server , hanya untuk mysql
    2017-05-04 15: 03: 24Z

Oracle 11g Release 2 mendukung fungsi LISTAGG. Dokumentasi di sini .

 
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.

Peringatan

Hati-hati mengimplementasikan fungsi ini jika ada kemungkinan string yang dihasilkan melebihi 4000 karakter. Itu akan melempar pengecualian. Jika itu yang terjadi maka Anda perlu menangani pengecualian atau memutar fungsi Anda sendiri yang mencegah string yang tergabung untuk lebih dari 4000 karakter.

    
45
2013-03-14 14: 30: 15Z
  1. Untuk versi Oracle yang lebih lama, wm_concat sempurna. Penggunaannya dijelaskan dalam tautan hadiah oleh Alex. Terima kasih Alex!
    2015-07-20 13: 04: 25Z
  2. LISTAGG bekerja dengan sempurna! Baca saja dokumen yang tertaut di sini. wm_concat dihapus dari versi 12c dan seterusnya.
    2016-06-22 18: 56: 44Z

Di SQL Server 2005 dan yang lebih baru, gunakan kueri di bawah ini untuk menyatukan baris.

 
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
    
33
2014-10-20 08: 49: 30Z
  1. Saya yakin ini gagal ketika nilainya mengandung simbol XML seperti < atau &.
    2013-08-13 01: 36: 56Z

Saya tidak memiliki akses ke SQL Server di rumah, jadi saya kira sintaksnya di sini, tetapi lebih atau kurang:

 
DECLARE @names VARCHAR(500)

SELECT @names = @names + ' ' + Name
FROM Names
    
26
2008-10-12 00: 16: 20Z
  1. Anda harus init @names menjadi sesuatu yang bukan nol, jika tidak Anda akan mendapatkan NULL secara keseluruhan; Anda juga perlu menangani pembatas (termasuk yang tidak perlu)
    2008-10-12 09: 10: 53Z
  2. satu-satunya masalah dengan pendekatan ini (yang saya gunakan sepanjang waktu) adalah Anda tidak dapat menanamkannya
    2012-11-23 22: 22: 29Z
  3. Untuk menghilangkan ruang terdepan, ubah kueri menjadi SELECT @names = @names + CASE WHEN LEN(@names)=0 THEN '' ELSE ' ' END + Name FROM Names
    2016-03-04 09: 15: 45Z
  4. Juga, Anda harus memeriksa bahwa Nama itu bukan nol, Anda dapat melakukannya dengan melakukan: SELECT @names = @names + ISNULL(' ' + Name, '')
    2016-03-18 10: 49: 30Z

Anda perlu membuat variabel yang akan menampung hasil akhir Anda dan memilihnya, seperti itu.

Solusi Termudah

 
DECLARE @char VARCHAR(MAX);

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

PRINT @char;
    
25
2016-11-15 21: 07: 57Z

Solusi CTE rekursif disarankan, tetapi tidak ada kode yang diberikan. Kode di bawah ini adalah contoh CTE rekursif - perhatikan bahwa meskipun hasilnya cocok dengan pertanyaan, data tidak cukup cocok dengan deskripsi yang diberikan, karena saya berasumsi bahwa Anda benar-benar ingin melakukan ini pada grup baris, tidak semua baris dalam tabel. Mengubahnya untuk mencocokkan semua baris dalam tabel dibiarkan sebagai latihan untuk pembaca.

 
;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
    
24
2012-08-09 21: 06: 05Z
  1. Untuk yang terperangah: kueri ini menyisipkan 12 baris (3 kolom) ke dalam basis sementara sementara, kemudian membuat Ekspresi Common Table rekursif (rCTE) dan kemudian meratakan kolom name menjadi string yang dipisahkan koma untuk 4 grup dari id s. Pada pandangan pertama, saya pikir ini lebih berfungsi daripada apa yang dilakukan kebanyakan solusi lain untuk SQL Server.
    2017-07-24 13: 34: 43Z
  2. @ knb: tidak yakin apakah itu pujian, kutukan, atau hanya kejutan. Tabel dasarnya adalah karena saya suka contoh saya benar-benar berfungsi, itu tidak benar-benar ada hubungannya dengan pertanyaan.
    2017-07-25 02: 20: 15Z

Dimulai dengan PostgreSQL 9.0 ini cukup sederhana:

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

Dalam versi sebelum 9.0 array_agg() dapat digunakan seperti yang ditunjukkan oleh hgmnz

    
23
2014-10-20 10: 42: 42Z
  1. Untuk melakukan ini dengan kolom yang bukan dari tipe teks, Anda perlu menambahkan tipe tulisan: SELECT string_agg(non_text_type::text, ',') FROM table
    2013-05-17 12: 05: 28Z
  2. @ TorbenKohlmeier: Anda hanya memerlukan itu untuk kolom non-karakter (mis. integer, desimal). Ini berfungsi dengan baik untuk varchar atau char
    2013-05-17 12: 11: 38Z

Dalam SQL Server vNext ini akan dibangun dengan fungsi STRING_AGG, baca lebih lanjut di sini: https://msdn.microsoft.com/en-us/library/mt790580.aspx

    
21
2017-01-10 15: 42: 49Z

Menggunakan XML membantu saya memisahkan baris dengan koma. Untuk koma ekstra kita dapat menggunakan fungsi ganti dari SQL Server. Alih-alih menambahkan koma, penggunaan AS 'data ()' akan menyatukan baris dengan spasi, yang nantinya dapat diganti dengan koma seperti sintaks yang ditulis di bawah ini.

 
REPLACE(
        (select FName AS 'data()'  from NameList  for xml path(''))
         , ' ', ', ') 
    
17
2012-02-26 18: 42: 55Z
  1. Ini adalah jawaban terbaik di sini menurut saya. Penggunaan variabel mendeklarasikan tidak baik ketika Anda harus bergabung di tabel lain, dan ini bagus dan pendek. Kerja bagus.
    2011-06-02 16: 22: 53Z
  2. itu tidak berfungsi dengan baik jika data FName sudah memiliki spasi, misalnya "Nama Saya"
    2011-06-08 15: 16: 32Z
  3. Benar-benar berfungsi untuk saya di ms-sql 2016 Pilih REPLACE ((pilih Name AS 'data ()' dari Brand Where Id IN (1,2,3, 4) untuk jalur xml ('')), '', ',') sebagai allBrands
    2017-04-28 10: 13: 38Z

Solusi siap pakai, tanpa koma tambahan:

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

Daftar kosong akan menghasilkan nilai NULL. Biasanya Anda akan memasukkan daftar ke kolom tabel atau variabel program: sesuaikan panjang maksimal 255 dengan kebutuhan Anda.

(Diwakar dan Jens Frandsen memberikan jawaban yang baik, tetapi perlu perbaikan.)

    
17
2012-02-26 20: 03: 20Z
  1. Ada spasi sebelum koma saat menggunakan ini :(
    2015-11-18 18: 23: 52Z
  2. Cukup ganti ', ' dengan ',' jika Anda tidak menginginkan ruang ekstra.
    2015-11-18 23: 17: 45Z
 
SELECT STUFF((SELECT ', ' + name FROM [table] FOR XML PATH('')), 1, 2, '')

Ini contohnya:

 
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
    
12
2018-02-28 16: 04: 05Z
  1. Terima kasih banyak telah memberikan solusi sekecil mungkin, bersama dengan contoh yang berhasil! Saya tidak tahu mengapa jawaban terpilih bekerja, atau bagaimana cara mereplikasinya.
    2018-03-19 14: 21: 08Z
 
DECLARE @Names VARCHAR(8000)
SELECT @name = ''
SELECT @Names = @Names + ',' + Names FROM People
SELECT SUBSTRING(2, @Names, 7998)

Ini menempatkan koma liar di awal.

Namun, jika Anda membutuhkan kolom lain, atau untuk CSV tabel anak, Anda perlu membungkusnya dalam bidang yang ditentukan pengguna skalar (UDF).

Anda dapat menggunakan jalur XML sebagai subquery yang berkorelasi di klausa SELECT juga (tapi saya harus menunggu sampai saya kembali bekerja karena Google tidak melakukan pekerjaan di rumah :-)

    
10
2012-02-26 18: 39: 58Z

Dengan jawaban lain, orang yang membaca jawabannya harus mengetahui tabel domain tertentu seperti kendaraan atau siswa. Tabel harus dibuat dan diisi dengan data untuk menguji solusi.

Di bawah ini adalah contoh yang menggunakan tabel SQL Server "Information_Schema.Columns". Dengan menggunakan solusi ini, tidak perlu membuat tabel atau data ditambahkan. Contoh ini membuat daftar nama kolom yang dipisahkan koma untuk semua tabel dalam database.

 
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 
    
9
2016-05-04 19: 31: 22Z

Untuk Oracle DB, lihat pertanyaan ini: Bagaimana beberapa baris dapat digabungkan menjadi satu di Oracle tanpa membuat prosedur tersimpan?

Jawaban terbaik tampaknya oleh @Emmanuel, menggunakan fungsi built-in LISTAGG (), tersedia di Oracle 11g Release 2 dan yang lebih baru.

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

seperti yang ditunjukkan @ user762952, dan menurut dokumentasi Oracle http://www.oracle-base.com/articles/misc/string-aggregation-techniques.php , fungsi WM_CONCAT () juga merupakan opsi. Tampaknya stabil, tetapi Oracle secara eksplisit merekomendasikan untuk tidak menggunakannya untuk aplikasi SQL apa pun, jadi gunakan risiko Anda sendiri.

Selain itu, Anda harus menulis fungsi Anda sendiri; dokumen Oracle di atas memiliki panduan tentang cara melakukannya.

    
7
2017-05-23 11: 47: 36Z

Saya sangat menyukai keanggunan dari Jawaban Dana . Hanya ingin membuatnya selesai.

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

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

-- Deleting last two symbols (', ')
SET @sSql = LEFT(@sSql, LEN(@sSql) - 1)
    
7
2017-05-23 11: 55: 19Z
  1. Jika Anda menghapus dua simbol terakhir ',', maka Anda perlu menambahkan ',' setelah Nama ('SELECT \@names = \@names + Name + ',' FROM Names '). Dengan begitu dua karakter terakhir akan selalu menjadi ','.
    2015-12-18 11: 04: 11Z
  2. Dalam kasus saya, saya perlu menyingkirkan koma terkemuka jadi ubah kueri menjadi SELECT @names = @names + CASE WHEN LEN(@names)=0 THEN '' ELSE ', ' END + Name FROM Names maka Anda tidak harus memotongnya setelah itu .
    2016-03-04 09: 13: 29Z

Untuk menghindari nilai nol, Anda dapat menggunakan CONCAT ()

 
DECLARE @names VARCHAR(500)
SELECT @names = CONCAT(@names, ' ', name) 
FROM Names
select @names
    
6
2015-02-12 12: 01: 27Z
  1. Akan menyenangkan mengetahui mengapa CONCAT berfungsi. Tautan ke MSDN akan menyenangkan.
    2016-09-20 08: 15: 03Z

Jawaban ini akan membutuhkan beberapa hak istimewa di server untuk bekerja.

Assemblies adalah pilihan yang baik untuk Anda. Ada banyak situs yang menjelaskan cara membuatnya. Yang saya pikir dijelaskan dengan sangat baik adalah ini satu

Jika mau, saya sudah membuat perakitan, dan dimungkinkan untuk mengunduh DLL di sini .

Setelah mengunduhnya, Anda harus menjalankan skrip berikut di SQL Server Anda:

 
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

Perhatikan bahwa jalur menuju perakitan mungkin dapat diakses ke server. Karena Anda telah berhasil melakukan semua langkah, Anda dapat menggunakan fungsi seperti:

 
SELECT dbo.Concat(field1, ',')
FROM Table1

Semoga ini membantu !!!

    
6
2015-05-08 01: 39: 06Z

Saya biasanya menggunakan pilih seperti ini untuk menggabungkan string dalam 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
    
5
2011-07-06 07: 06: 01Z

Jika Anda ingin berurusan dengan nol, Anda dapat melakukannya dengan menambahkan klausa di mana atau menambahkan COALESCE lain di sekitar yang pertama.

 
DECLARE @Names VARCHAR(8000) 
SELECT @Names = COALESCE(COALESCE(@Names + ', ', '') + Name, @Names) FROM People
    
5
2011-07-27 20: 05: 13Z

Contoh lengkap MySQL:

Kami memiliki Pengguna yang dapat memiliki banyak Data dan kami ingin memiliki keluaran, di mana kami dapat melihat semua Data Pengguna dalam daftar:

 

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

Pengaturan Tabel:

 
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);

Permintaan:

 
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
2015-07-22-22 07: 51: 12Z

Di Oracle, ini adalah wm_concat. Saya percaya fungsi ini tersedia di 10g rilis dan lebih tinggi.

    
4
2012-02-26 18: 44: 21Z

Ini bisa berguna juga

 
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

kembali

 
Peter,Paul,Mary
    
4
2013-10-25 08: 14: 23Z
  1. Sayangnya perilaku ini tampaknya tidak didukung secara resmi. MSDN mengatakan: "Jika suatu variabel direferensikan dalam daftar pilih, harus diberi nilai skalar atau pernyataan SELECT hanya akan mengembalikan satu baris. " Dan ada orang yang mengamati masalah: sqlmag.com/sql- server /multi-baris-penugasan-variabel-dan-pesanan
    2013-12-05 09: 11: 08Z

Metode ini hanya berlaku untuk basis data Teradata Aster karena menggunakan fungsi NPATH-nya.

Sekali lagi, kami memiliki tabel Siswa

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

Kemudian dengan NPATH hanya SELECT tunggal:

 
SELECT * FROM npath(
  ON Students
  PARTITION BY SubjectID
  ORDER BY StudentName
  MODE(nonoverlapping)
  PATTERN('A*')
  SYMBOLS(
    'true' as A
  )
  RESULT(
    FIRST(SubjectID of A) as SubjectID,
    ACCUMULATE(StudentName of A) as StudentName
  )
);

Hasil:

 
SubjectID       StudentName
----------      -------------
1               [John, Mary, Sam]
2               [Alaina, Edward]
    
3
2013-11-15 20: 26: 03Z
sumber ditempatkan sini