Как объединить текст из нескольких строк в одну текстовую строку на сервере SQL? - PullRequest
1709 голосов
/ 12 октября 2008

Рассмотрим таблицу базы данных, содержащую имена, с тремя строками:

Peter
Paul
Mary

Есть ли простой способ превратить это в одну строку Peter, Paul, Mary?

Ответы [ 45 ]

26 голосов
/ 12 октября 2008

У меня нет доступа к SQL Server дома, поэтому я предполагаю синтаксис здесь, но он более или менее:

DECLARE @names VARCHAR(500)

SELECT @names = @names + ' ' + Name
FROM Names
25 голосов
/ 16 ноября 2016

Вам нужно создать переменную, в которой будет храниться ваш конечный результат, и выбрать его, например, так.

Самое простое решение

DECLARE @char VARCHAR(MAX);

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

PRINT @char;
24 голосов
/ 10 августа 2012

Было предложено рекурсивное решение CTE, но код не предоставлен. Приведенный ниже код является примером рекурсивного CTE - обратите внимание, что хотя результаты соответствуют вопросу, данные не вполне соответствуют данному описанию, так как я предполагаю, что вы действительно хотите сделать это группы строк, а не все строки в таблице. Изменение его для соответствия всем строкам таблицы оставлено читателю в качестве упражнения.

;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
23 голосов
/ 17 ноября 2012

Начиная с PostgreSQL 9.0, это довольно просто:

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

В версиях до 9.0 array_agg() может использоваться, как показано hgmnz

21 голосов
/ 21 ноября 2016

В SQL Server vNext это будет встроено функцией STRING_AGG, подробнее об этом здесь: https://msdn.microsoft.com/en-us/library/mt790580.aspx

17 голосов
/ 03 февраля 2012

Готовое решение без лишних запятых:

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

Пустой список приведет к значению NULL. Обычно вы вставляете список в столбец таблицы или переменную программы: установите максимальную длину 255 в соответствии с вашими потребностями.

(Дивакар и Йенс Франдсен дали хорошие ответы, но нуждаются в улучшении.)

17 голосов
/ 07 апреля 2011

Использование XML помогло мне получить строки, разделенные запятыми. Для дополнительной запятой мы можем использовать функцию замены SQL Server. Вместо добавления запятой использование AS data () объединит строки с пробелами, которые впоследствии можно будет заменить на запятые в качестве синтаксиса, приведенного ниже.

REPLACE(
        (select FName AS 'data()'  from NameList  for xml path(''))
         , ' ', ', ') 
12 голосов
/ 25 января 2018
SELECT STUFF((SELECT ', ' + name FROM [table] FOR XML PATH('')), 1, 2, '')

Вот пример:

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
10 голосов
/ 13 октября 2008
DECLARE @Names VARCHAR(8000)
SELECT @name = ''
SELECT @Names = @Names + ',' + Names FROM People
SELECT SUBSTRING(2, @Names, 7998)

Это ставит запятую в начале.

Однако, если вам нужны другие столбцы или для CSV дочерней таблицы, вам нужно обернуть это в скалярное пользовательское поле (UDF).

Вы также можете использовать путь XML как коррелированный подзапрос в предложении SELECT (но мне придется подождать, пока я не вернусь к работе, потому что Google не выполняет работу дома: -)

9 голосов
/ 04 мая 2016

При других ответах человек, читающий ответ, должен знать конкретную таблицу предметной области, например, автомобиль или студент. Таблица должна быть создана и заполнена данными для тестирования решения.

Ниже приведен пример, в котором используется таблица «Information_Schema.Columns» SQL Server. Используя это решение, не нужно создавать таблицы или добавлять данные. В этом примере создается список имен столбцов, разделенных запятыми, для всех таблиц в базе данных.

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 
...