Мне нужно как-то сгруппировать строки при объединении определенного столбца, я не уверен, как бы я это сделал. Ниже приводится пример того, что мне нужно.

CREATE TABLE People(
PersonName varchar(100),
PersonAge int
)

INSERT INTO People
SELECT 'bill', 21

INSERT INTO People
SELECT 'harry', 21

INSERT INTO People
SELECT 'wesley', 21

INSERT INTO People
SELECT 'tom', 42

INSERT INTO People
SELECT 'paul', 42

INSERT INTO People
SELECT 'phil', 53

Обычный выбор из этой таблицы даст следующее:

bill    21
harry   21
wesley  21
tom     42
paul    42
phil    53

Мне нужно следующее:

bill, harry, wesley    21
tom,paul               42
phil                   53

Я не уверен, возможно ли это, но было бы очень полезно, если бы кто-нибудь знал, как это сделать. Заранее спасибо.

2
DarrynC 16 Июн 2009 в 13:47

5 ответов

Лучший ответ

Это сложная проблема. Для более подробного изучения этого см. Этот отличный пост:

http://www.simple-talk.com/sql/t-sql-programming/concatenating-row-values-in-transact-sql/

Для простого решения я использовал курсор, он выполняет свою работу:

create procedure
doIt
as

create table #out
(people varchar(2000) null, -- assumed max length of concatenated string
age int)

insert into #out(age)
select distinct personAge from people

declare @str varchar(2000)
select @str = isnull(@str,'') + personname +',' from people

declare @age int
declare cur cursor for select age from #out

open cur
fetch next from cur into @age

while @@fetch_status =0
begin 
    set @str = ''
    select @str = isnull(@str,'') + personname +',' from people where personage = @age
    update #out set people = left(@str,len(@str)-1) where age=@age
    fetch next from cur into @age   
end

close cur
deallocate cur

select * from #out
1
tekBlues 16 Июн 2009 в 10:07

ВЫБРАТЬ p1.personage, (SELECT personName + ',' FROM people p2 WHERE p2.personage = p1.personage ORDER BY personName FOR XML PATH ('')) КАК РЕЗУЛЬТАТЫ ОТ людей p1 ГРУППА ПО персонажу;

2
Raj 16 Июн 2009 в 21:35

Вот способ без курсоров, используя ссылку, которую tekBlues поместил в свой пост:

WITH CTE ( PersonAge, person_list, person_name, length )
AS 
( 
SELECT PersonAge, CAST( '' AS VARCHAR(8000) ), CAST( '' AS VARCHAR(8000) ), 0
FROM People
GROUP BY PersonAge
UNION ALL
SELECT p.PersonAge, 
    CAST( person_list + CASE WHEN length = 0 THEN '' ELSE ', ' END + PersonName AS VARCHAR(8000) ),
    CAST( PersonName AS VARCHAR(8000)), length + 1
FROM CTE c
INNER JOIN People p ON c.PersonAge = p.PersonAge
WHERE p.PersonName > c.person_name 
)
SELECT PersonAge, person_list
FROM 
( 
SELECT PersonAge, person_list, RANK() OVER ( PARTITION BY PersonAge ORDER BY length DESC )
FROM CTE 
) D ( PersonAge, person_list, rank )
WHERE rank = 1 ;  
0
Craig HB 16 Июн 2009 в 10:51

Это серьезная проблема в Sql Server. Вы можете, например, создать настраиваемый агрегат конкатенации строк. Но это требует, чтобы вы загрузили сборку .NET на свой Sql Server; не все администраторы баз данных согласятся с этим.

На стороне клиента это действительно просто. Почему бы вам не заняться решением этой клиентской части?

0
Andomar 16 Июн 2009 в 11:41

Если вы используете MySQL, это максимально просто.

SELECT GROUP_CONCAT(PersonName SEPARATOR ', ') as name, PersonAge 
FROM People GROUP BY PersonAge

Также есть варианты ORDER и DISTINCT :)

0
vava 8 Сен 2009 в 09:34