Преобразование нескольких строк в одну с запятой в качестве разделителя [дубликат]


этот вопрос уже есть ответ здесь:

  • Как объединить текст из нескольких строк в одну текстовую строку в SQL server? 44 ответы

Если я вопрос SELECT username FROM Users Я получаю такой результат:

username
--------
Paul
John
Mary

но что мне действительно нужно один строка со всеми значениями, разделенными запятой, например это:

Paul, John, Mary

как мне это сделать?

10 60

10 ответов:

Это должно работать для вас. Протестировано вплоть до SQL 2000.

create table #user (username varchar(25))

insert into #user (username) values ('Paul')
insert into #user (username) values ('John')
insert into #user (username) values ('Mary')

declare @tmp varchar(250)
SET @tmp = ''
select @tmp = @tmp + username + ', ' from #user

select SUBSTRING(@tmp, 0, LEN(@tmp))
 select
   distinct  
    stuff((
        select ',' + u.username
        from users u
        where u.username = username
        order by u.username
        for xml path('')
    ),1,1,'') as userlist
from users
group by username

была опечатка раньше, выше работает

хороший обзор нескольких подходов:

http://blogs.msmvps.com/robfarley/2007/04/07/coalesce-is-not-the-answer-to-string-concatentation-in-t-sql/

статьи копия -

Coalesce не является ответом на конкатенацию строк в T-SQL я видел много сообщений на протяжении многих лет об использовании функции COALESCE для получения конкатенации строк, работающих в T-SQL. Это один из примеров здесь (заимствовано из Readifarian Marc Риди).

DECLARE @categories varchar(200)
SET @categories = NULL

SELECT @categories = COALESCE(@categories + ',','') + Name
FROM Production.ProductCategory

SELECT @categories

этот запрос может быть довольно эффективным, но необходимо проявлять осторожность, и использование COALESCE должно быть правильно понято. COALESCE-это версия ISNULL, которая может принимать более двух параметров. Он возвращает первое в списке параметров, которое не является нулевым. Так что на самом деле это не имеет ничего общего с конкатенацией, и следующий фрагмент кода точно такой же - без использования COALESCE:

DECLARE @categories varchar(200)
SET @categories = ''

SELECT @categories = @categories + ',' + Name
FROM Production.ProductCategory

SELECT @categories

но неупорядоченный характер баз данных делает это ненадежно. Вся причина, по которой T-SQL (пока) не имеет функции конкатенации, заключается в том, что это агрегат, для которого важен порядок элементов. Используя этот метод присваивания переменных конкатенации строк, вы можете обнаружить, что ответ, который возвращается, не имеет всех значений в нем, особенно если вы хотите, чтобы подстроки были помещены в определенном порядке. Рассмотрим следующее, что на моей машине только возвращает', аксессуары', когда я хотел его вернуть ', Велосипеды, Одежда, Комплектующие, Аксессуары':

DECLARE @categories varchar(200)
SET @categories = NULL

SELECT @categories = COALESCE(@categories + ',','') + Name
FROM Production.ProductCategory
ORDER BY LEN(Name)

SELECT @categories

гораздо лучше использовать метод, который учитывает порядок и который был включен в SQL2005 специально для конкатенации строк-для пути XML (")

SELECT ',' + Name
FROM Production.ProductCategory
ORDER BY LEN(Name)
FOR XML PATH('') 

в сообщении, которое я сделал недавно, сравнивая GROUP BY и DISTINCT при использовании подзапросов, я продемонстрировал использование for XML PATH("). Взгляните на это и вы увидите, как это работает в подзапросе. Функция "материал" - это только там, чтобы снять ведущую запятой.

USE tempdb;
GO
CREATE TABLE t1 (id INT, NAME VARCHAR(MAX));
INSERT t1 values (1,'Jamie');
INSERT t1 values (1,'Joe');
INSERT t1 values (1,'John');
INSERT t1 values (2,'Sai');
INSERT t1 values (2,'Sam');
GO

select
    id,
    stuff((
        select ',' + t.[name]
        from t1 t
        where t.id = t1.id
        order by t.[name]
        for xml path('')
    ),1,1,'') as name_csv
from t1
group by id
; 

for XML PATH - это одна из единственных ситуаций, в которой вы можете использовать ORDER BY в подзапросе. Другой-сверху. И когда вы используете безымянный столбец и для пути XML ("), вы получите прямую конкатенацию, без тегов XML. Это означает, что строки будут закодированы в HTML, поэтому, если вы объединяете строки, которые могут иметь символ

основываясь на ответе mwigdahls. если вам также нужно сделать группировку здесь, как заставить его выглядеть

group, csv
'group1', 'paul, john'
'group2', 'mary'

    --drop table #user
create table #user (groupName varchar(25), username varchar(25))

insert into #user (groupname, username) values ('apostles', 'Paul')
insert into #user (groupname, username) values ('apostles', 'John')
insert into #user (groupname, username) values ('family','Mary')


select
    g1.groupname
    , stuff((
        select ', ' + g.username
        from #user g        
        where g.groupName = g1.groupname        
        order by g.username
        for xml path('')
    ),1,2,'') as name_csv
from #user g1
group by g1.groupname

вы можете использовать этот запрос для выполнения вышеуказанной задачи:

DECLARE @test NVARCHAR(max)  
SELECT @test = COALESCE(@test + ',', '') + field2 FROM #test
SELECT field2 = @test 

для подробного и пошагового объяснения посетите следующую ссылку http://oops-solution.blogspot.com/2011/11/sql-server-convert-table-column-data.html

DECLARE @EmployeeList varchar(100)

SELECT @EmployeeList = COALESCE(@EmployeeList + ', ', '') + 
   CAST(Emp_UniqueID AS varchar(5))
FROM SalesCallsEmployees
WHERE SalCal_UniqueID = 1

SELECT @EmployeeList

источник: http://www.sqlteam.com/article/using-coalesce-to-build-comma-delimited-string

чистым и гибким решением в MS SQL Server 2005/2008 является создание агрегатной функции CLR.

вы найдете довольно много статей (с кодом) на google.

похоже в этой статье проведет вас через весь процесс, используя C#.

в SQLite это проще. Я думаю, что есть аналогичные реализации для MySQL, MSSql и Orable

CREATE TABLE Beatles (id integer, name string );
INSERT INTO Beatles VALUES (1, "Paul");
INSERT INTO Beatles VALUES (2, "John");
INSERT INTO Beatles VALUES (3, "Ringo");
INSERT INTO Beatles VALUES (4, "George");
SELECT GROUP_CONCAT(name, ',') FROM Beatles;

вы можете использовать stuff() для преобразования строк в значения, разделенные запятыми

select
EmployeeID,
stuff((
  SELECT ',' + FPProjectMaster.GroupName 
      FROM     FPProjectInfo AS t INNER JOIN
              FPProjectMaster ON t.ProjectID = FPProjectMaster.ProjectID
      WHERE  (t.EmployeeID = FPProjectInfo.EmployeeID)
              And t.STatusID = 1
              ORDER BY t.ProjectID
       for xml path('')
       ),1,1,'') as name_csv
from FPProjectInfo
group by EmployeeID;

спасибо @AlexKuznetsov за ссылку, чтобы получить этот ответ.

Если вы выполняете это через PHP, что об этом?

$hQuery = mysql_query("SELECT * FROM users");
while($hRow = mysql_fetch_array($hQuery)) {
    $hOut .= $hRow['username'] . ", ";
}
$hOut = substr($hOut, 0, strlen($hOut) - 1);
echo $hOut;