Преобразование нескольких строк в одну с запятой в качестве разделителя [дубликат]
Вопрос
На этот вопрос уже есть ответ здесь:
Если я выпущу SELECT username FROM Users
Я получаю такой результат:
username -------- Paul John Mary
но что мне действительно нужно, так это один строка со всеми значениями, разделенными запятыми, например:
Paul, John, Mary
Как мне это сделать?
Решение
Это должно сработать для вас.Протестировано вплоть до 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
раньше была опечатка, вышеописанное работает
хороший обзор нескольких подходов:
Копия статьи -
Объединение не является решением проблемы конкатенации строк в T-SQL. За прошедшие годы я видел много сообщений об использовании функции COALESCE для работы конкатенации строк в T-SQL.Это один из приведенных здесь примеров (заимствован у редифарианца Марка Райди).
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 специально для целей конкатенации строк - FOR XML PATH('')
SELECT ',' + Name
FROM Production.ProductCategory
ORDER BY LEN(Name)
FOR XML PATH('')
В недавно опубликованной статье, посвященной сравнению GROUP BY и DISTINCT при использовании подзапросов, я продемонстрировал использование FOR XML PATH('').Посмотрите на это, и вы увидите, как это работает в подзапросе.Функция «STUFF» предназначена только для удаления начальной запятой.
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 в подзапросе.Другой - ТОП.А когда вы используете безымянный столбец и FOR XML PATH(''), вы получите прямую конкатенацию без тегов XML.Это означает, что строки будут закодированы в HTML, поэтому, если вы объединяете строки, которые могут иметь символ < (и т. д.), возможно, вам следует исправить это впоследствии, но в любом случае это по-прежнему лучший способ объединения строк. в SQL-сервере 2005.
основываясь на ответе Мвигдала.если вам также нужно выполнить группировку, вот как это будет выглядеть так
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 @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
Вы можете использовать этот запрос для выполнения вышеуказанной задачи:
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
В 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;
Чистым и гибким решением в MS SQL Server 2005/2008 является создание агрегатной функции CLR.
Вы найдете довольно много статей (с кодом) на Google.
Это выглядит как Эта статья проведет вас через весь процесс с использованием C#.
вы можете использовать материал() для преобразования строк в значения, разделенные запятыми
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;