2 Stimmen

Gruppieren von Zeilen bei der Verkettung einer bestimmten Spalte mit einem Begrenzungszeichen

Ich muss irgendwie Zeilen gruppieren, während eine bestimmte Spalte verkettet wird, ich bin nicht sicher, wie ich dies tun würde. Das Folgende ist ein Beispiel für das, was ich brauche.

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

Ein normaler Select aus dieser Tabelle führt zu folgendem Ergebnis:

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

Ich brauche Folgendes:

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

Ich bin mir nicht sicher, ob dies möglich ist, aber es wäre wirklich hilfreich, wenn jemand weiß, wie man es macht. Vielen Dank im Voraus.

2voto

Raj Punkte 10413

SELECT p1.personage, ( SELECT Personenname + ',' FROM personen p2 WHERE p2.personage = p1.personage ORDER BY Personenname FOR XML PATH('') ) AS Ergebnisse FROM Personen p1 GROUP BY personage ;

1voto

tekBlues Punkte 5647

Dies ist ein schwieriges Problem. Eine ausführliche Behandlung dieses Themas finden Sie in diesem ausgezeichneten Beitrag:

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

Für eine einfache Lösung habe ich einen Cursor verwendet, der die Aufgabe erfüllt:

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

0voto

Craig Punkte 3996

Hier ist ein Weg ohne Cursors mit dem Link, den tekBlues in seinem Beitrag angegeben hat:

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 ;

0voto

Andomar Punkte 224164

Dies ist ein schwieriges Problem in Sql Server. Sie könnten zum Beispiel eine benutzerdefiniertes Aggregat zur String-Verkettung . Dazu müssen Sie jedoch eine .NET-Assembly in Ihren SQL-Server laden; nicht alle DBAs sind damit einverstanden.

Auf der Client-Seite ist dies sehr einfach. Warum suchen Sie nicht nach einer Lösung auf der Client-Seite?

0voto

vava Punkte 23765

Wenn Sie MySQL verwenden, ist es so einfach, wie es nur sein kann

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

Es gibt auch die Optionen ORDER und DISTINCT :)

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X