web-dev-qa-db-ger.com

Wie kann ich in SQL Server Text aus mehreren Zeilen zu einer einzelnen Textzeichenfolge verketten?

Betrachten Sie eine Datenbanktabelle mit Namen und drei Zeilen:

Peter
Paul
Mary

Gibt es eine einfache Möglichkeit, dies in eine einzelne Zeichenfolge von Peter, Paul, Mary umzuwandeln?

1766
JohnnyM

Wenn Sie mit SQL Server 2017 oder Azure arbeiten, lesen Sie Antwort von Mathieu Renda .

Ich hatte ein ähnliches Problem, als ich versuchte, zwei Tabellen mit Eins-zu-Viele-Beziehungen zu verknüpfen. In SQL 2005 stellte ich fest, dass die XML PATH -Methode die Verkettung der Zeilen sehr einfach handhaben kann.

Wenn es eine Tabelle mit dem Namen STUDENTS gibt

SubjectID       StudentName
----------      -------------
1               Mary
1               John
1               Sam
2               Alaina
2               Edward

Ergebnis, das ich erwartet hatte, war:

SubjectID       StudentName
----------      -------------
1               Mary, John, Sam
2               Alaina, Edward

Ich habe den folgenden T-SQL verwendet:

SELECT Main.SubjectID,
       LEFT(Main.Students,Len(Main.Students)-1) As "Students"
FROM
    (
        SELECT DISTINCT ST2.SubjectID, 
            (
                SELECT ST1.StudentName + ',' AS [text()]
                FROM dbo.Students ST1
                WHERE ST1.SubjectID = ST2.SubjectID
                ORDER BY ST1.SubjectID
                FOR XML PATH ('')
            ) [Students]
        FROM dbo.Students ST2
    ) [Main]

Sie können das Gleiche auf kompaktere Weise tun, wenn Sie die Kommas am Anfang einschließen und substring verwenden, um das erste zu überspringen, sodass Sie keine Unterabfrage ausführen müssen:

SELECT DISTINCT ST2.SubjectID, 
    SUBSTRING(
        (
            SELECT ','+ST1.StudentName  AS [text()]
            FROM dbo.Students ST1
            WHERE ST1.SubjectID = ST2.SubjectID
            ORDER BY ST1.SubjectID
            FOR XML PATH ('')
        ), 2, 1000) [Students]
FROM dbo.Students ST2
1315
Ritesh

Diese Antwort kann nerwartete Ergebnisse zurückgeben. Verwenden Sie für konsistente Ergebnisse eine der FOR XML PATH-Methoden, die in anderen Antworten aufgeführt sind.

Verwenden Sie COALESCE:

DECLARE @Names VARCHAR(8000) 
SELECT @Names = COALESCE(@Names + ', ', '') + Name 
FROM People

Nur eine Erklärung (da diese Antwort relativ regelmäßige Ansichten zu bekommen scheint):

  • Coalesce ist wirklich nur ein hilfreicher Cheat, der zwei Dinge erreicht:

1) Es ist nicht erforderlich, @Names mit einem leeren Zeichenfolgenwert zu initialisieren.

2) Am Ende muss kein zusätzlicher Abscheider entfernt werden.

  • Die obige Lösung führt zu falschen Ergebnissen, wenn eine Zeile einen NULL -Namenswert hat (wenn es einen NULL gibt, Das NULL macht @NamesNULL nach dieser Zeile, und die nächste Zeile beginnt von vorne als wieder eine leere Zeichenfolge. Mit einer von zwei Lösungen leicht zu beheben:
DECLARE @Names VARCHAR(8000) 
SELECT @Names = COALESCE(@Names + ', ', '') + Name
FROM People
WHERE Name IS NOT NULL

oder:

DECLARE @Names VARCHAR(8000) 
SELECT @Names = COALESCE(@Names + ', ', '') + 
    ISNULL(Name, 'N/A')
FROM People

Je nachdem, welches Verhalten Sie wünschen (die erste Option filtert nur NULL aus, die zweite Option hält sie in der Liste mit einer Markierungsnachricht [Ersetzen Sie 'N/A' durch was auch immer für dich angemessen ist]).

965
Chris Shaffer

Eine Methode, die noch nicht über den Befehl XMLdata() in MS SQL Server angezeigt wird, ist:

Angenommen, die Tabelle heißt NameList und eine Spalte heißt FName.

SELECT FName + ', ' AS 'data()' 
FROM NameList 
FOR XML PATH('')

kehrt zurück:

"Peter, Paul, Mary, "

Nur das zusätzliche Komma muss behandelt werden.

Edit: Wie in @ NReilinghs Kommentar übernommen, können Sie das nachstehende Komma mit der folgenden Methode entfernen. Angenommen, die gleichen Tabellen- und Spaltennamen:

STUFF(REPLACE((SELECT '#!' + LTRIM(RTRIM(FName)) AS 'data()' FROM NameList
FOR XML PATH('')),' #!',', '), 1, 2, '') as Brands
338
jens frandsen

SQL Server 2017+ und SQL Azure: STRING_AGG

Ab der nächsten Version von SQL Server können wir endlich zeilenübergreifend verketten, ohne auf Variablen oder XML-Hexerei zurückgreifen zu müssen.

STRING_AGG (Transact-SQL)

Ohne Gruppierung

SELECT STRING_AGG(Name, ', ') AS Departments
FROM HumanResources.Department;

Mit Gruppierung:

SELECT GroupName, STRING_AGG(Name, ', ') AS Departments
FROM HumanResources.Department
GROUP BY GroupName;

Mit Gruppierung und Untersortierung

SELECT GroupName, STRING_AGG(Name, ', ') WITHIN GROUP (ORDER BY Name ASC) AS Departments
FROM HumanResources.Department 
GROUP BY GroupName;
319
Mathieu Renda

In SQL Server 2005

SELECT Stuff(
  (SELECT N', ' + Name FROM Names FOR XML PATH(''),TYPE)
  .value('text()[1]','nvarchar(max)'),1,2,N'')

In SQL Server 2016

sie können die FOR JSON-Syntax verwenden

d.h.

SELECT per.ID,
Emails = JSON_VALUE(
   REPLACE(
     (SELECT _ = em.Email FROM Email em WHERE em.Person = per.ID FOR JSON PATH)
    ,'"},{"_":"',', '),'$[0]._'
) 
FROM Person per

Und das Ergebnis wird

Id  Emails
1   [email protected]
2   NULL
3   [email protected], [email protected]

Dies funktioniert auch dann, wenn Ihre Daten ungültige XML-Zeichen enthalten

der '"},{"_":"' ist sicher, denn wenn Ihre Daten '"},{"_":"', enthalten, werden sie an "},{\"_\":\" weitergeleitet.

Sie können ', ' durch ein beliebiges Zeichenfolgentrennzeichen ersetzen


Und in SQL Server 2017 Azure SQL-Datenbank

Sie können die neue STRING_AGG-Funktion verwenden

277
Steven Chong

In MySQL gibt es eine Funktion GROUP_CONCAT () , mit der Sie die Werte aus mehreren Zeilen zusammenfassen können. Beispiel:

SELECT 1 AS a, GROUP_CONCAT(name ORDER BY name ASC SEPARATOR ', ') AS people 
FROM users 
WHERE id IN (1,2,3) 
GROUP BY a
112
Darryl Hein

Verwenden Sie COALESCE - Weitere Informationen finden Sie hier

Zum Beispiel:

102

103

104

Dann schreiben Sie unten Code in SQL Server,

Declare @Numbers AS Nvarchar(MAX) -- It must not be MAX if you have few numbers 
SELECT  @Numbers = COALESCE(@Numbers + ',', '') + Number
FROM   TableName where Number IS NOT NULL

SELECT @Numbers

Die Ausgabe wäre:

102,103,104
55
pedram

Postgres-Arrays sind fantastisch. Beispiel:

Erstellen Sie einige Testdaten:

postgres=# \c test
You are now connected to database "test" as user "hgimenez".
test=# create table names (name text);
CREATE TABLE                                      
test=# insert into names (name) values ('Peter'), ('Paul'), ('Mary');                                                          
INSERT 0 3
test=# select * from names;
 name  
-------
 Peter
 Paul
 Mary
(3 rows)

Aggregieren Sie sie in einem Array:

test=# select array_agg(name) from names;
 array_agg     
------------------- 
 {Peter,Paul,Mary}
(1 row)

Konvertieren Sie das Array in eine durch Kommas getrennte Zeichenfolge:

test=# select array_to_string(array_agg(name), ', ') from names;
 array_to_string
-------------------
 Peter, Paul, Mary
(1 row)

GETAN

Seit PostgreSQL 9.0 ist es noch einfacher .

47
hgmnz

Oracle 11g Release 2 unterstützt die LISTAGG-Funktion. Dokumentation hier .

COLUMN employees FORMAT A50

SELECT deptno, LISTAGG(ename, ',') WITHIN GROUP (ORDER BY ename) AS employees
FROM   emp
GROUP BY deptno;

    DEPTNO EMPLOYEES
---------- --------------------------------------------------
        10 CLARK,KING,MILLER
        20 ADAMS,FORD,JONES,SCOTT,SMITH
        30 ALLEN,BLAKE,JAMES,MARTIN,TURNER,WARD

3 rows selected.

Warnung

Seien Sie vorsichtig bei der Implementierung dieser Funktion, wenn die Möglichkeit besteht, dass die resultierende Zeichenfolge mehr als 4000 Zeichen umfasst. Es wird eine Ausnahme auslösen. In diesem Fall müssen Sie entweder die Ausnahme behandeln oder eine eigene Funktion ausführen, die verhindert, dass die verknüpfte Zeichenfolge mehr als 4000 Zeichen enthält.

45
Alex

Verwenden Sie in SQL Server 2005 und höher die folgende Abfrage, um die Zeilen zu verketten.

DECLARE @t table
(
    Id int,
    Name varchar(10)
)
INSERT INTO @t
SELECT 1,'a' UNION ALL
SELECT 1,'b' UNION ALL
SELECT 2,'c' UNION ALL
SELECT 2,'d' 

SELECT ID,
stuff(
(
    SELECT ','+ [Name] FROM @t WHERE Id = t.Id FOR XML PATH('')
),1,1,'') 
FROM (SELECT DISTINCT ID FROM @t ) t
33

Ich habe zu Hause keinen Zugriff auf einen SQL Server, daher schätze ich die Syntax hier, aber es ist mehr oder weniger:

DECLARE @names VARCHAR(500)

SELECT @names = @names + ' ' + Name
FROM Names
26
Dana

Sie müssen eine Variable erstellen, die Ihr Endergebnis enthält, und diese wie folgt auswählen.

Einfachste Lösung

DECLARE @char VARCHAR(MAX);

SELECT @char = COALESCE(@char + ', ' + [column], [column]) 
FROM [table];

PRINT @char;
25
Tigerjz32

Eine rekursive CTE-Lösung wurde vorgeschlagen, es wurde jedoch kein Code bereitgestellt. Der folgende Code ist ein Beispiel für einen rekursiven CTE. Beachten Sie, dass, obwohl die Ergebnisse mit der Frage übereinstimmen, die Daten nicht ganz mit der angegebenen Beschreibung übereinstimmen, da ich davon ausgehe, dass Sie dies wirklich für Gruppen von Zeilen tun möchten, nicht für alle Zeilen in Der Tisch. Das Ändern, damit es mit allen Zeilen in der Tabelle übereinstimmt, wird dem Leser als Übung überlassen.

;WITH basetable AS (
    SELECT
        id,
        CAST(name AS VARCHAR(MAX)) name, 
        ROW_NUMBER() OVER (Partition BY id ORDER BY seq) rw, 
        COUNT(*) OVER (Partition BY id) recs 
    FROM (VALUES
        (1, 'Johnny', 1),
        (1, 'M', 2), 
        (2, 'Bill', 1),
        (2, 'S.', 4),
        (2, 'Preston', 5),
        (2, 'Esq.', 6),
        (3, 'Ted', 1),
        (3, 'Theodore', 2),
        (3, 'Logan', 3),
        (4, 'Peter', 1),
        (4, 'Paul', 2),
        (4, 'Mary', 3)
    ) g (id, name, seq)
),
rCTE AS (
    SELECT recs, id, name, rw
    FROM basetable
    WHERE rw = 1

    UNION ALL

    SELECT b.recs, r.ID, r.name +', '+ b.name name, r.rw + 1
    FROM basetable b
    INNER JOIN rCTE r ON b.id = r.id AND b.rw = r.rw + 1
)
SELECT name
FROM rCTE
WHERE recs = rw AND ID=4
25
jmoreno

Ab PostgreSQL 9.0 ist das ganz einfach:

select string_agg(name, ',') 
from names;

In Versionen vor 9.0 kann array_agg() wie von hgmnz gezeigt verwendet werden

23

In SQL Server vNext wird dies mit der STRING_AGG-Funktion integriert. Weitere Informationen hierzu finden Sie hier: https://msdn.Microsoft.com/en-us/library/mt790580.aspx

21
Henrik Fransas

Die Verwendung von XML hat mir geholfen, Zeilen durch Kommas zu trennen. Für das zusätzliche Komma können wir die Ersetzungsfunktion von SQL Server verwenden. Anstatt ein Komma einzufügen, werden die Zeilen mit Leerzeichen verknüpft, die später durch Kommas ersetzt werden können (siehe unten).

REPLACE(
        (select FName AS 'data()'  from NameList  for xml path(''))
         , ' ', ', ') 
18
Diwakar

Eine gebrauchsfertige Lösung ohne zusätzliche Kommas:

select substring(
        (select ', '+Name AS 'data()' from Names for xml path(''))
       ,3, 255) as "MyList"

Eine leere Liste führt zu einem NULL-Wert. Normalerweise fügen Sie die Liste in eine Tabellenspalte oder Programmvariable ein: Passen Sie die maximale Länge von 255 an Ihre Bedürfnisse an.

(Diwakar und Jens Frandsen gaben gute Antworten, mussten aber verbessert werden.)

17
Daniel Reis
SELECT STUFF((SELECT ', ' + name FROM [table] FOR XML PATH('')), 1, 2, '')

Hier ist ein Beispiel:

DECLARE @t TABLE (name VARCHAR(10))
INSERT INTO @t VALUES ('Peter'), ('Paul'), ('Mary')
SELECT STUFF((SELECT ', ' + name FROM @t FOR XML PATH('')), 1, 2, '')
--Peter, Paul, Mary
12
Max Szczurek
DECLARE @Names VARCHAR(8000)
SELECT @name = ''
SELECT @Names = @Names + ',' + Names FROM People
SELECT SUBSTRING(2, @Names, 7998)

Damit steht das Streukomma am Anfang.

Wenn Sie jedoch andere Spalten oder eine untergeordnete Tabelle als CSV-Datei benötigen, müssen Sie diese in ein skalares benutzerdefiniertes Feld (UDF) einschließen.

Sie können den XML-Pfad auch als korrelierte Unterabfrage in der SELECT-Klausel verwenden (aber ich muss warten, bis ich wieder zur Arbeit gehe, da Google zu Hause keine Arbeit erledigt :-)

10
gbn

Bei den anderen Antworten muss der Person, die die Antwort liest, eine bestimmte Domänentabelle bekannt sein, z. B. Fahrzeug oder Schüler. Die Tabelle muss erstellt und mit Daten gefüllt werden, um eine Lösung zu testen.

Unten finden Sie ein Beispiel, das die SQL Server-Tabelle "Information_Schema.Columns" verwendet. Mit dieser Lösung müssen keine Tabellen erstellt oder Daten hinzugefügt werden. In diesem Beispiel wird eine durch Kommas getrennte Liste von Spaltennamen für alle Tabellen in der Datenbank erstellt.

SELECT
    Table_Name
    ,STUFF((
        SELECT ',' + Column_Name
        FROM INFORMATION_SCHEMA.Columns Columns
        WHERE Tables.Table_Name = Columns.Table_Name
        ORDER BY Column_Name
        FOR XML PATH ('')), 1, 1, ''
    )Columns
FROM INFORMATION_SCHEMA.Columns Tables
GROUP BY TABLE_NAME 

Siehe für Oracle-DBs diese Frage: Wie können mehrere Zeilen in Oracle zu einer verkettet werden, ohne eine gespeicherte Prozedur zu erstellen?

Die beste Antwort scheint @Emmanuel zu sein, der die in Oracle 11g Release 2 und höher integrierte Funktion LISTAGG () verwendet.

SELECT question_id,
   LISTAGG(element_id, ',') WITHIN GROUP (ORDER BY element_id)
FROM YOUR_TABLE;
GROUP BY question_id

wie @ user762952 hervorhob und laut Oracle-Dokumentation http://www.Oracle-base.com/articles/misc/string-aggregation-techniques.php ist die WM_CONCAT () -Funktion auch eine Möglichkeit. Es scheint stabil zu sein, aber Oracle rät ausdrücklich davon ab, es für SQL-Anwendungen zu verwenden. Verwenden Sie es daher auf eigenes Risiko.

Ansonsten müssen Sie Ihre eigene Funktion schreiben. Das obige Oracle-Dokument enthält eine Anleitung dazu.

7
ZeroK

Ich mochte die Eleganz von Danas Antwort . Ich wollte es nur komplett machen.

DECLARE @names VARCHAR(MAX)
SET @names = ''

SELECT @names = @names + ', ' + Name FROM Names 

-- Deleting last two symbols (', ')
SET @sSql = LEFT(@sSql, LEN(@sSql) - 1)
7
Oleg Sakharov

Um Nullwerte zu vermeiden, können Sie CONCAT () verwenden.

DECLARE @names VARCHAR(500)
SELECT @names = CONCAT(@names, ' ', name) 
FROM Names
select @names
6
Rapunzo

Für diese Antwort sind einige Serverrechte erforderlich.

Assemblies sind eine gute Option für Sie. Es gibt viele Sites, die erklären, wie man es erstellt. Das, von dem ich denke, dass es sehr gut erklärt ist, ist dieses eins

Wenn Sie möchten, habe ich die Assembly bereits erstellt und es ist möglich, die DLL hier herunterzuladen.

Nachdem Sie es heruntergeladen haben, müssen Sie das folgende Skript in Ihrem SQL Server ausführen:

CREATE Assembly concat_Assembly 
   AUTHORIZATION dbo 
   FROM '<PATH TO Concat.dll IN SERVER>' 
   WITH PERMISSION_SET = SAFE; 
GO 

CREATE AGGREGATE dbo.concat ( 

    @Value NVARCHAR(MAX) 
  , @Delimiter NVARCHAR(4000) 

) RETURNS NVARCHAR(MAX) 
EXTERNAL Name concat_Assembly.[Concat.Concat]; 
GO  

sp_configure 'clr enabled', 1;
RECONFIGURE

Beachten Sie, dass der Pfad zur Assembly möglicherweise für den Server zugänglich ist. Nachdem Sie alle Schritte erfolgreich ausgeführt haben, können Sie die folgende Funktion verwenden:

SELECT dbo.Concat(field1, ',')
FROM Table1

Ich hoffe es hilft!!!

6
Nizam

Normalerweise verwende ich select wie folgt, um Zeichenfolgen in SQL Server zu verketten:

with lines as 
( 
  select 
    row_number() over(order by id) id, -- id is a line id
    line -- line of text.
  from
    source -- line source
), 
result_lines as 
( 
  select 
    id, 
    cast(line as nvarchar(max)) line 
  from 
    lines 
  where 
    id = 1 
  union all 
  select 
    l.id, 
    cast(r.line + N', ' + l.line as nvarchar(max))
  from 
    lines l 
    inner join 
    result_lines r 
    on 
      l.id = r.id + 1 
) 
select top 1 
  line
from
  result_lines
order by
  id desc

Vollständiges MySQL-Beispiel:

Wir haben Benutzer, die viele Daten haben können, und wir möchten eine Ausgabe, in der wir alle Benutzerdaten in einer Liste sehen können:

Ergebnis:

___________________________
| id   |  rowList         |
|-------------------------|
| 0    | 6, 9             |
| 1    | 1,2,3,4,5,7,8,1  |
|_________________________|

Tabelleneinstellung:

CREATE TABLE `Data` (
  `id` int(11) NOT NULL,
  `user_id` int(11) NOT NULL
) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=latin1;


INSERT INTO `Data` (`id`, `user_id`) VALUES
(1, 1),
(2, 1),
(3, 1),
(4, 1),
(5, 1),
(6, 0),
(7, 1),
(8, 1),
(9, 0),
(10, 1);


CREATE TABLE `User` (
  `id` int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;


INSERT INTO `User` (`id`) VALUES
(0),
(1);

Abfrage:

SELECT User.id, GROUP_CONCAT(Data.id ORDER BY Data.id) AS rowList FROM User LEFT JOIN Data ON User.id = Data.user_id GROUP BY User.id
5
user1767754

Wenn Sie mit Nullen umgehen möchten, können Sie eine where-Klausel hinzufügen oder eine weitere COALESCE-Klausel um die erste Klausel hinzufügen.

DECLARE @Names VARCHAR(8000) 
SELECT @Names = COALESCE(COALESCE(@Names + ', ', '') + Name, @Names) FROM People
5
Pramod

Dies kann auch nützlich sein

create table #test (id int,name varchar(10))
--use separate inserts on older versions of SQL Server
insert into #test values (1,'Peter'), (1,'Paul'), (1,'Mary'), (2,'Alex'), (3,'Jack')

DECLARE @t VARCHAR(255)
SELECT @t = ISNULL(@t + ',' + name, name) FROM #test WHERE id = 1
select @t
drop table #test

kehrt zurück

Peter,Paul,Mary
4
endo64

In Oracle ist es wm_concat. Ich glaube, dass diese Funktion in der 10g-Version und höher verfügbar ist.

4
user762952

Diese Methode gilt nur für Teradata Aster-Datenbanken, da die NPATH-Funktion verwendet wird.

Wieder haben wir Tischstudenten

SubjectID       StudentName
----------      -------------
1               Mary
1               John
1               Sam
2               Alaina
2               Edward

Dann ist es bei NPATH nur noch Single SELECT:

SELECT * FROM npath(
  ON Students
  PARTITION BY SubjectID
  ORDER BY StudentName
  MODE(nonoverlapping)
  PATTERN('A*')
  SYMBOLS(
    'true' as A
  )
  RESULT(
    FIRST(SubjectID of A) as SubjectID,
    ACCUMULATE(StudentName of A) as StudentName
  )
);

Ergebnis:

SubjectID       StudentName
----------      -------------
1               [John, Mary, Sam]
2               [Alaina, Edward]
3
topchef

Nicht, dass ich eine Leistungsanalyse durchgeführt hätte, da meine Liste weniger als 10 Elemente enthielt, aber ich war erstaunt, nachdem ich die 30 ungeraden Antworten durchgesehen hatte. Ich hatte immer noch eine Wendung bei einer ähnlichen Antwort, die bereits gegeben wurde, ähnlich wie bei der Verwendung von COALESCE für eine einzelne Gruppenliste und nicht Ich muss meine Variable nicht einmal setzen (der Standardwert ist sowieso NULL) und es wird davon ausgegangen, dass alle Einträge in meiner Quelldatentabelle nicht leer sind:

DECLARE @MyList VARCHAR(1000), @Delimiter CHAR(2) = ', '
SELECT @MyList = CASE WHEN @MyList > '' THEN @MyList + @Delimiter ELSE '' END + FieldToConcatenate FROM MyData

Ich bin sicher, dass COALESCE intern dieselbe Idee verwendet. Hoffen wir, dass MS das an mir nicht ändert.

3
Glen

Hier ist die Komplettlösung, um dies zu erreichen:

-- Table Creation
CREATE TABLE Tbl
( CustomerCode    VARCHAR(50)
, CustomerName    VARCHAR(50)
, Type VARCHAR(50)
,Items    VARCHAR(50)
)

insert into Tbl
SELECT 'C0001','Thomas','BREAKFAST','Milk'
union SELECT 'C0001','Thomas','BREAKFAST','Bread'
union SELECT 'C0001','Thomas','BREAKFAST','Egg'
union SELECT 'C0001','Thomas','LUNCH','Rice'
union SELECT 'C0001','Thomas','LUNCH','Fish Curry'
union SELECT 'C0001','Thomas','LUNCH','Lessy'
union SELECT 'C0002','JOSEPH','BREAKFAST','Bread'
union SELECT 'C0002','JOSEPH','BREAKFAST','Jam'
union SELECT 'C0002','JOSEPH','BREAKFAST','Tea'
union SELECT 'C0002','JOSEPH','Supper','Tea'
union SELECT 'C0002','JOSEPH','Brunch','Roti'

-- function creation
GO
CREATE  FUNCTION [dbo].[fn_GetItemsByType]
(   
    @CustomerCode VARCHAR(50)
    ,@Type VARCHAR(50)
)
RETURNS @ItemType TABLE  ( Items VARCHAR(5000) )
AS
BEGIN

        INSERT INTO @ItemType(Items)
    SELECT  STUFF((SELECT distinct ',' + [Items]
         FROM Tbl 
         WHERE CustomerCode = @CustomerCode
            AND [email protected]
            FOR XML PATH(''))
        ,1,1,'') as  Items



    RETURN 
END

GO

-- fianl Query
DECLARE @cols AS NVARCHAR(MAX),
    @query  AS NVARCHAR(MAX)

select @cols = STUFF((SELECT distinct ',' + QUOTENAME(Type) 
                    from Tbl
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

set @query = 'SELECT CustomerCode,CustomerName,' + @cols + '
             from 
             (
                select  
                    distinct CustomerCode
                    ,CustomerName
                    ,Type
                    ,F.Items
                    FROM Tbl T
                    CROSS APPLY [fn_GetItemsByType] (T.CustomerCode,T.Type) F
            ) x
            pivot 
            (
                max(Items)
                for Type in (' + @cols + ')
            ) p '

execute(@query) 
3
Ravi Pipaliya

--SQL Server 2005+

CREATE TABLE dbo.Students
(
    StudentId INT
    , Name VARCHAR(50)
    , CONSTRAINT PK_Students PRIMARY KEY (StudentId)
);

CREATE TABLE dbo.Subjects
(
    SubjectId INT
    , Name VARCHAR(50)
    , CONSTRAINT PK_Subjects PRIMARY KEY (SubjectId)
);

CREATE TABLE dbo.Schedules
(
    StudentId INT
    , SubjectId INT
    , CONSTRAINT PK__Schedule PRIMARY KEY (StudentId, SubjectId)
    , CONSTRAINT FK_Schedule_Students FOREIGN KEY (StudentId) REFERENCES dbo.Students (StudentId)
    , CONSTRAINT FK_Schedule_Subjects FOREIGN KEY (SubjectId) REFERENCES dbo.Subjects (SubjectId)
);

INSERT dbo.Students (StudentId, Name) VALUES
    (1, 'Mary')
    , (2, 'John')
    , (3, 'Sam')
    , (4, 'Alaina')
    , (5, 'Edward')
;

INSERT dbo.Subjects (SubjectId, Name) VALUES
    (1, 'Physics')
    , (2, 'Geography')
    , (3, 'French')
    , (4, 'Gymnastics')
;

INSERT dbo.Schedules (StudentId, SubjectId) VALUES
    (1, 1)      --Mary, Physics
    , (2, 1)    --John, Physics
    , (3, 1)    --Sam, Physics
    , (4, 2)    --Alaina, Geography
    , (5, 2)    --Edward, Geography
;

SELECT 
    sub.SubjectId
    , sub.Name AS [SubjectName]
    , ISNULL( x.Students, '') AS Students
FROM
    dbo.Subjects sub
    OUTER APPLY
    (
        SELECT 
            CASE ROW_NUMBER() OVER (ORDER BY stu.Name) WHEN 1 THEN '' ELSE ', ' END
            + stu.Name
        FROM
            dbo.Students stu
            INNER JOIN dbo.Schedules sch
                ON stu.StudentId = sch.StudentId
        WHERE
            sch.SubjectId = sub.SubjectId
        ORDER BY
            stu.Name
        FOR XML PATH('')
    ) x (Students)
;
3
Graeme

Wie wäre es damit:

   ISNULL(SUBSTRING(REPLACE((select ',' FName as 'data()' from NameList for xml path('')), ' ,',', '), 2, 300), '') 'MyList'

Wobei die "300" eine beliebige Breite haben kann, unter Berücksichtigung der maximalen Anzahl von Elementen, von denen Sie denken, dass sie angezeigt werden.

2
Hans Bluh

Eine Möglichkeit, dies in SQL Server zu tun, besteht darin, den Tabelleninhalt als XML (für XML raw) zurückzugeben, das Ergebnis in eine Zeichenfolge zu konvertieren und die Tags durch "," zu ersetzen.

2
Manu
SELECT PageContent = Stuff(
    (   SELECT PageContent
        FROM dbo.InfoGuide
        WHERE CategoryId = @CategoryId
          AND SubCategoryId = @SubCategoryId
        for xml path(''), type
    ).value('.[1]','nvarchar(max)'),
    1, 1, '')
FROM dbo.InfoGuide info
2
Muhammad Bilal

Im Folgenden finden Sie eine einfache PL/SQL-Prozedur zum Implementieren des angegebenen Szenarios mit "basic loop" und "rownum".

Tabellendefinition

CREATE TABLE "NAMES" ("NAME" VARCHAR2(10 BYTE))) ;

Fügen wir nun Werte in diese Tabelle ein

INSERT INTO NAMES VALUES('PETER');
INSERT INTO NAMES VALUES('PAUL');
INSERT INTO NAMES VALUES('MARY');

Die Prozedur beginnt hier

DECLARE 

MAXNUM INTEGER;
CNTR INTEGER := 1;
C_NAME NAMES.NAME%TYPE;
NSTR VARCHAR2(50);

BEGIN

SELECT MAX(ROWNUM) INTO MAXNUM FROM NAMES;

LOOP

SELECT NAME INTO  C_NAME FROM 
(SELECT ROWNUM RW, NAME FROM NAMES ) P WHERE P.RW = CNTR;

NSTR := NSTR ||','||C_NAME;
CNTR := CNTR + 1;
EXIT WHEN CNTR > MAXNUM;

END LOOP;

dbms_output.put_line(SUBSTR(NSTR,2));

END;

Ergebnis

PETER,PAUL,MARY
2
Pooja Bhat

Obwohl es zu spät ist und bereits viele Lösungen hat. Hier ist eine einfache Lösung für MySQL:

SELECT t1.id,
        GROUP_CONCAT(t1.id) ids
 FROM table t1 JOIN table t2 ON (t1.id = t2.id)
 GROUP BY t1.id
2
Shahbaz

@ User1460901 Sie können Folgendes versuchen:

WITH cte_base AS (
    SELECT CustomerCode, CustomerName,
    CASE WHEN Typez = 'Breakfast' THEN Items ELSE NULL END AS 'BREAKFAST'
    , CASE WHEN Typez = 'Lunch' THEN Items ELSE NULL END AS 'LUNCH'
    FROM #Customer
    )
    SELECT distinct CustomerCode, CustomerName,
    SUBSTRING(
    (   
        SELECT ','+BREAKFAST AS [text()]
        FROM cte_base b1
        WHERE b1.CustomerCode = b2.CustomerCode AND b1.CustomerName = b2.CustomerName
        ORDER BY b1.BREAKFAST
        FOR XML PATH('')
        ), 2, 1000
    ) [BREAKFAST], 
    SUBSTRING(
    (   
        SELECT ','+LUNCH AS [text()]
        FROM cte_base b1
        WHERE b1.CustomerCode = b2.CustomerCode AND b1.CustomerName = b2.CustomerName
        ORDER BY b1.LUNCH
        FOR XML PATH('')
        ), 2, 1000
    ) [LUNCH]
    FROM cte_base b2
1
Aura

Mit TABLE-Typ ist es extrem einfach. Stellen wir uns vor, Ihre Tabelle heißt Students und hat die Spalte name.

declare @rowsCount INT
declare @i INT = 1
declare @names varchar(max) = ''

DECLARE @MyTable TABLE
(
  Id int identity,
  Name varchar(500)
)
insert into @MyTable select name from Students
set @rowsCount = (select COUNT(Id) from @MyTable)

while @i < @rowsCount
begin
 set @names = @names + ', ' + (select name from @MyTable where Id = @i)
 set @i = @i + 1
end
select @names

Dieses Beispiel wurde in MS SQL Server 2008 R2 getestet

1
Max Tkachenko

Mit einer rekursiven Abfrage können Sie dies tun:

-- Create example table
CREATE TABLE tmptable (NAME VARCHAR(30)) ;

-- Insert example data
INSERT INTO tmptable VALUES('PETER');
INSERT INTO tmptable VALUES('PAUL');
INSERT INTO tmptable VALUES('MARY');

-- Recurse query
with tblwithrank as (
select * , row_number() over(order by name) rang , count(*) over() NbRow
from tmptable
),
tmpRecursive as (
select *, cast(name as varchar(2000)) as AllName from tblwithrank  where rang=1
union all
select f0.*,  cast(f0.name + ',' + f1.AllName as varchar(2000)) as AllName 
from tblwithrank f0 inner join tmpRecursive f1 on f0.rang=f1.rang +1 
)
select AllName from tmpRecursive
where rang=NbRow
1
Esperento57

Es gibt noch ein paar weitere Möglichkeiten in Oracle,

    create table name
    (first_name varchar2(30));

    insert into name values ('Peter');
    insert into name values ('Paul');
    insert into name values ('Mary');

    Solution 1:
    select substr(max(sys_connect_by_path (first_name, ',')),2) from (select rownum r, first_name from name ) n start with r=1 connect by prior r+1=r
    o/p=> Peter,Paul,Mary

    Soution 2:
    select  rtrim(xmlagg (xmlelement (e, first_name || ',')).extract ('//text()'), ',') first_name from name
    o/p=> Peter,Paul,Mary

Wir können RECUSRSIVITY, WITH CTE, union ALL wie folgt verwenden

declare @mytable as table(id int identity(1,1), str nvarchar(100))
insert into @mytable values('Peter'),('Paul'),('Mary')

declare @myresult as table(id int,str nvarchar(max),ind int, R# int)

;with cte as(select id,cast(str as nvarchar(100)) as str, cast(0 as int) ind from @mytable
union all
select t2.id,cast(t1.str+',' +t2.str as nvarchar(100)) ,t1.ind+1 from cte t1 inner join @mytable t2 on t2.id=t1.id+1)
insert into @myresult select *,row_number() over(order by ind) R# from cte

select top 1 str from @myresult order by R# desc
0
Kemal AL GAZZAH

auf Chris Shaffer Antwort

wenn sich Ihre Daten wiederholen könnten

Tom
ALi
John
ALi
Tom
Mike

Anstatt Tom,ALi,John,ALi,Tom,Mike zu haben

Sie können DISTINCT verwenden, um Duplikate zu vermeiden und Tom,ALi,John,Mike zu erhalten.

DECLARE @Names VARCHAR(8000) 
SELECT DISTINCT @Names = COALESCE(@Names + ',', '') + Name
FROM People
WHERE Name IS NOT NULL
SELECT @Names
0
asmgx