Преобразование нескольких строк в одну с запятой в качестве разделителя [дубликат]
этот вопрос уже есть ответ здесь:
- Как объединить текст из нескольких строк в одну текстовую строку в SQL server? 44 ответы
Если я вопрос SELECT username FROM Users
Я получаю такой результат:
username -------- Paul John Mary
но что мне действительно нужно один строка со всеми значениями, разделенными запятой, например это:
Paul, John, Mary
как мне это сделать?
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
была опечатка раньше, выше работает
хороший обзор нескольких подходов:
статьи копия -
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 за ссылку, чтобы получить этот ответ.