SQL Server에서 여러 행의 텍스트를 단일 텍스트 문자열로 연결하는 방법은 무엇입니까?


1912

세 개의 행이있는 이름을 보유한 데이터베이스 테이블을 고려하십시오.

Peter
Paul
Mary

이것을 단일 문자열로 바꾸는 쉬운 방법이 Peter, Paul, Mary있습니까?


26
SQL Server와 관련된 답변을 보려면 이 질문을 시도 하십시오 .
Matt Hamilton

17
MySQL의 경우이 답변 에서 Group_Concat 을 확인하십시오
Pykler

26
다음 버전의 SQL Server가 FOR XML PATH를 사용하지 않고 여러 행 문자열 연결을 우아하게 해결하는 새로운 기능을 제공하기를 바랍니다.
Pete Alvin

4
SQL은 아니지만 한 번만 사용하는 경우 목록을이 브라우저 도구 인 convert.town/column-to-comma-separated-list
Stack Man

3
Oracle에서는 지원되지 않는 WM_CONCAT (COLUMN_NAME)이라는 기능이 있기 전에 11g r2의 LISTAGG (COLUMN_NAME)을 사용할 수 있습니다.
Richard

답변:


1432

SQL Server 2017 또는 Azure를 사용하는 경우 Mathieu Renda answer를 참조하십시오 .

일대 다 관계로 두 테이블을 조인하려고 할 때 비슷한 문제가 발생했습니다. SQL 2005에서 XML PATH메소드가 행의 연결을 매우 쉽게 처리 할 수 있음을 발견했습니다 .

라는 테이블이 있다면 STUDENTS

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

내가 예상 한 결과는 다음과 같습니다.

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

나는 다음을 사용했다 T-SQL:

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]

처음에 쉼표를 연결 substring하고 첫 번째 쉼표 를 건너 뛰어 하위 쿼리를 수행 할 필요가없는 경우 더 간단한 방법으로 동일한 작업을 수행 할 수 있습니다.

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

13
훌륭한 솔루션. : 당신은 HTML에서와 같은 특수 문자를 처리해야하는 경우 다음은 도움이 될 수 있습니다 롭 팔리가 : XML의 PATH ( '')의 경우와 특수 문자를 처리 .

10
이름이 같은 XML 문자가 포함 된 경우 분명히이 작동하지 않습니다 <&. @BenHinman의 의견을 참조하십시오.
Sam

23
주의 :이 방법은의 문서화되지 않은 동작에 의존합니다 FOR XML PATH (''). 즉, 패치 나 업데이트로 인해이 기능이 변경 될 수 있으므로 신뢰할 수있는 것으로 간주해서는 안됩니다. 기본적으로 더 이상 사용되지 않는 기능에 의존합니다.
베이컨 비트

26
@Whelkaholism 결론은 FOR XML임의의 문자열을 연결하지 않고 XML을 생성하는 것입니다. 즉,이 탈출 이유 &, <그리고 >XML 엔티티 코드로 ( &amp;, &lt;, &gt;). 나는 또한 탈출 것으로 가정 "'&quot;&apos;속성에뿐만 아니라. 그건 아니 GROUP_CONCAT() , string_agg(), array_agg(), listagg(), 등 당신은 어떤 메이크업의 그것은 그렇게 할 수 경우에도 마찬가지입니다. 우리 Microsoft가 적절한 기능을 구현하도록 요구하면서 시간을 보내야 합니다.
베이컨 비트

13
좋은 소식 : MS SQL Server가 string_aggv.Next에 추가 될 예정입니다. 이 모든 것이 사라질 수 있습니다.
Jason C

1008

이 답변은 예기치 않은 결과 를 반환 할 수 있습니다. 일관된 결과를 얻으려면 다른 답변에 자세히 나와있는 FOR XML PATH 메서드 중 하나를 사용하십시오.

사용 COALESCE:

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

약간의 설명 (이 답변은 상대적으로 규칙적인 견해를 갖기 때문에) :

  • Coalesce는 실제로 다음 두 가지를 수행하는 유용한 사기꾼입니다.

1) @Names빈 문자열 값 으로 초기화 할 필요가 없습니다 .

2) 끝에서 여분의 분리기를 떼어 낼 필요가 없습니다.

  • 행이있는 경우이 솔루션은 위의 잘못된 결과를 얻을 수 NULL 가있는 경우 (이름 값을 NULLNULL을 만들 것입니다 @Names NULL을 해당 행 후, 다음 행은 다시 빈 문자열로 시작됩니다. 쉽게 두 가지 중 하나를 고정 솔루션 :
DECLARE @Names VARCHAR(8000) 
SELECT @Names = COALESCE(@Names + ', ', '') + Name
FROM People
WHERE Name IS NOT NULL

또는:

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

원하는 동작에 따라 첫 번째 옵션은 NULL을 필터링 하므로 두 번째 옵션은 마커 메시지와 함께 목록에 유지합니다 ( 'N / A'를 적절한 것으로 바꿉니다).


72
분명히 합병은 목록을 만드는 것과 아무런 관련이 없으며 NULL 값이 포함되지 않도록합니다.
Graeme Perrow 2012

17
@Graeme Perrow NULL 값을 배제하지 않습니다 (WHERE가 필요합니다- 입력 값 중 하나가 NULL이면 결과잃을 것입니다 ). 이 접근법 에서는 NULL + non-NULL-> NULL NULL이 아닌 + NULL-> NULL; 또한 @Name은 기본적으로 NULL이며 실제로이 속성은 ','를 추가해야하는지 여부를 결정하기 위해 여기에서 암시 적 센티넬로 사용됩니다.

62
이 연결 방법은 특정 계획으로 쿼리를 실행하는 SQL Server에 의존합니다. 이 방법을 사용하여 (ORDER BY를 추가하여) 잡혔습니다. 적은 수의 행을 처리 할 때 제대로 작동했지만 더 많은 데이터를 사용하면 SQL Server는 다른 계획을 선택하여 연결이없는 첫 번째 항목을 선택했습니다. 참고 이 문서 Anith 상원 의원에 의해을
fbarber

17
이 메소드는 tSQL 변수를 사용하므로 선택 목록 또는 where-clause에서 하위 조회로 사용할 수 없습니다. 이러한 경우 @Ritesh
R에서

11
신뢰할 수있는 연결 방법이 아닙니다. 지원되지 않으므로 사용해서는 안됩니다 (예 : Microsoft의 경우 support.microsoft.com/en-us/kb/287515 , connect.microsoft.com/SQLServer/Feedback/Details/704389 ). 경고없이 변경 될 수 있습니다. stackoverflow.com/questions/5031204/ 에서 논의 된 XML PATH 기술을 사용 하십시오. 여기에 더 썼습니다 : marc.durdin.net/2015/07/…
Marc Durdin

454

SQL Server 2017 이상 및 SQL Azure : STRING_AGG

다음 버전의 SQL Server부터는 변수 또는 XML 마녀에 의존하지 않고도 행 전체를 연결할 수 있습니다.

STRING_AGG (Transact-SQL)

그룹화하지 않고

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

그룹화 :

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

그룹화 및 하위 분류

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

2
또한 CLR 솔루션과 달리 정렬을 제어 할 수 있습니다.
canon

STRING_AGG
InspiredBy

GROUP BY가없는 경우 정렬 할 수있는 방법이 있습니까 (따라서 "그룹화 없음"예)?
RuudvK

업데이트 : 다음을 수행했지만 더 깔끔한 방법이 있습니까? SELECT STRING_AGG (이름, ',') AS 부서의 부서 (SELECT TOP 100000 이름 FROM HumanResources.Department ORDER BY 이름) D;
RuudvK

362

XML data()MS SQL Server에서 명령을 통해 아직 표시되지 않은 방법 은 다음과 같습니다.

FName이라는 하나의 열이있는 NameList라는 테이블을 가정합니다.

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

보고:

"Peter, Paul, Mary, "

여분의 쉼표 만 처리해야합니다.

편집 : @NReilingh의 의견에서 채택한 것처럼 다음 방법을 사용하여 후행 쉼표를 제거 할 수 있습니다. 동일한 테이블 및 열 이름을 가정합니다.

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

15
이런거 대단해! 예제에서와 같이 자체적으로 실행될 때 결과는 하이퍼 링크로 형식화되며, SSMS에서 클릭하면 데이터가 포함 된 새 창이 열리지 만 더 큰 쿼리의 일부로 사용되면 문자열로 나타납니다. 문자열입니까? 또는이 데이터를 사용할 응용 프로그램에서 다르게 취급 해야하는 XML입니까?
Ben

10
이 방법은 또한 <및>과 같은 XML 이스케이프 문자입니다. 따라서 '<b>'+ FName + '</ b>'을 선택하면 "<John> / b & gt; Paul ..."이됩니다.
Lukáš Lánský

8
깔끔한 솔루션. 추가하지 않아도 + ', '연결된 모든 요소 사이에 단일 공백이 여전히 추가됩니다.
Baodad

8
@Baodad 거래의 일부인 것 같습니다. 추가 된 토큰 문자를 바꾸면이 문제를 해결할 수 있습니다. 예를 들어, 이것은 모든 길이에 대해 완벽한 쉼표로 구분 된 목록을 수행합니다.SELECT STUFF(REPLACE((SELECT '#!'+city AS 'data()' FROM #cityzip FOR XML PATH ('')),' #!',', '),1,2,'')
NReilingh

1
와우, 실제로 data () 및 replace를 사용하여 테스트 할 때보 다 성능이 뛰어납니다. 정말 이상해
NReilingh

306

에서 SQL Server 2005의

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

SQL Server 2016에서

FOR JSON 구문을 사용할 수 있습니다

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

결과는

Id  Emails
1   abc@gmail.com
2   NULL
3   def@gmail.com, xyz@gmail.com

데이터에 유효하지 않은 XML 문자가 포함되어 있어도 작동합니다.

'"},{"_":"'당신의 데이터가 포함 된 경우 때문에 안전 '"},{"_":"',이 탈출한다"},{\"_\":\"

', '문자열 구분 기호로 바꿀 수 있습니다


그리고 SQL Server 2017에서 Azure SQL Database

새로운 STRING_AGG 기능을 사용할 수 있습니다


3
STUFF 기능을 잘 사용하여 선행 두 문자를 nix합니다.
David

3
'as <label>'을 추가하여 선택 목록에서 쉽게 사용할 수 있기 때문에이 솔루션이 가장 좋습니다. @Ritesh 솔루션 으로이 작업을 수행하는 방법을 잘 모르겠습니다.
R. Schreurs

13
이 옵션은 또한 다음과 같은 취소 탈출 XML의 reserverd 문자를 처리하기 때문에이 허용 대답보다 낫다 <, >, &, 등 어떤 FOR XML PATH('')자동으로 이스케이프됩니다.
BateTech

이것은 문제가 해결로 멋진 반응이다 지금은 내가 2017 / 푸른 사용할 수하고자하는 SQL의 다른 버전에서 일을하는 가장 좋은 방법을 제공합니다
크리스 워드

120

MySQL에는 GROUP_CONCAT () 함수가 있는데 ,이를 통해 여러 행의 값을 연결할 수 있습니다. 예:

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

잘 작동합니다. 그러나 내가 사용 SEPARATOR '", "'하면 마지막 항목 끝에 일부 문자가 누락됩니다. 왜 이런 일이 일어날 수 있습니까?
gooleem

@gooleem 나는 당신이 무슨 뜻인지 명확하지 않지만이 기능은 항목 사이에 구분 기호를 넣지 만 나중에는 아닙니다. 답변이 아닌 경우 새 질문을 게시하는 것이 좋습니다.
Darryl Hein

내 필요에 따라 @DarrylHein 위의 구분 기호를 사용했습니다. 그러나 이것은 출력의 마지막 부분에서 일부 문자를 잘라냅니다. 이것은 매우 이상하며 버그 인 것 같습니다. 나는 해결책이 없다. 나는 방금 해결했다.
gooleem

기본적으로 작동합니다. 두 가지 고려해야 할 : 1) 당신의 열이 아닌 경우 CHAR, 당신이 그것을 캐스팅 할 필요가, 예를 통해 GROUP_CONCAT( CAST(id AS CHAR(8)) ORDER BY id ASC SEPARATOR ',')2) 많은 값이 올 경우, 당신은 증가 할 전망 group_concat_max_len에서 작성된 stackoverflow.com/a/1278210/1498405
hardmooth

58

COALESCE 사용 - 여기에서 자세히 알아보기

예를 들어 :

102

103

104

그런 다음 SQL 서버에서 아래 코드를 작성하십시오.

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

결과는 다음과 같습니다.

102,103,104

2
이것은 FOR XML이 제공하는 인코딩 문제를 피하기 때문에 실제로 최고의 솔루션 IMO입니다. 나는 사용 Declare @Numbers AS Nvarchar(MAX)했고 잘 작동했다. 사용하지 않는 것이 좋은 이유를 설명해 주시겠습니까?
EvilDr

7
이 솔루션은 이미 8 년 전에 게시되었습니다! stackoverflow.com/a/194887/986862
Andre Figueiredo

이 쿼리가 왜 ???를 반환합니까? 키릴 문자 대신 기호? 이것은 단지 출력 문제입니까?
Akmal Salikhov

48

Postgres 어레이는 훌륭합니다. 예:

테스트 데이터를 작성하십시오.

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)

그것들을 배열로 모으십시오 :

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

배열을 쉼표로 구분 된 문자열로 변환하십시오.

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

끝난

PostgreSQL 9.0 이후로 훨씬 더 쉽습니다 .


예를 들어 대괄호로 묶은 직원 ID와 같이 두 개 이상의 열이 필요한 경우 concat 연산자를 사용하십시오. select array_to_string(array_agg(name||'('||id||')'
Richard Fox

sql-server 에는 적용되지 않으며 mysql
GoldBishop

46

Oracle 11g Release 2는 LISTAGG 기능을 지원합니다. 여기에 설명서가 있습니다 .

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.

경고

결과 문자열이 4000자를 넘을 가능성이있는 경우이 기능을 신중하게 구현하십시오. 예외가 발생합니다. 이 경우 예외를 처리하거나 결합 된 문자열이 4000자를 넘지 않도록하는 고유 한 함수를 롤링해야합니다.


1
이전 버전의 Oracle의 경우 wm_concat이 완벽합니다. 사용법은 Alex의 링크 선물에 설명되어 있습니다. 알렉스!
toscanelli

LISTAGG완벽하게 작동합니다! 여기에 링크 된 문서를 읽으십시오. wm_concat버전 12c 이상에서 제거되었습니다.
ass

34

SQL Server 2005 이상에서 아래 쿼리를 사용하여 행을 연결하십시오.

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

2
나는 값이 같은 XML 기호가 포함되어있는 경우이 오류가 발생 믿고 <또는 &.
Sam

28

집에서 SQL Server에 액세스 할 수 없으므로 여기 구문을 추측 할 수 있지만 다소 있습니다.

DECLARE @names VARCHAR(500)

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

11
@names를 널이 아닌 다른 것으로 초기화해야한다. 그렇지 않으면 전체적으로 NULL을 얻는다. 또한 구분자를 처리해야합니다 (불필요한 것 포함)
Marc Gravell

3
이 접근법의 유일한 문제점은 (내가 항상 사용하는) 당신이 그것을 포함시킬 수 없다는 것입니다
ekkis

1
선행 공간을 제거하려면 쿼리를 다음과 같이 변경하십시오.SELECT @names = @names + CASE WHEN LEN(@names)=0 THEN '' ELSE ' ' END + Name FROM Names
Tian van Heerden

또한 Name이 null이 아닌지 확인해야합니다.SELECT @names = @names + ISNULL(' ' + Name, '')
Vita1ij

28

재귀 CTE 솔루션이 제안되었지만 코드는 제공되지 않았습니다. 아래 코드는 재귀 CTE의 예입니다. 결과가 질문을 일치하지만은 참고 자료는하지 않는 것을 확실히 난 당신이 정말 행 그룹, 테이블의 모든 행에이 일을한다고 가정으로, 주어진 설명을 일치합니다. 표의 모든 행과 일치하도록 변경하는 것은 독자의 연습으로 남습니다.

;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

1
flabbergasted의 경우 :이 쿼리는 12 개의 행 (3 개의 열)을 임시 기본 테이블에 삽입 한 다음 재귀 공통 테이블 식 (rCTE)을 생성 한 다음 name 열을 쉼표로 구분 된 4 개의 그룹 으로 묶습니다id . 언뜻보기에 이것은 대부분의 다른 SQL Server 솔루션보다 더 많은 작업이라고 생각합니다.
knb

2
@knb : 그것이 칭찬, 비난, 또는 놀람인지 확실하지 않습니다. 기본 테이블은 내 예제가 실제로 작동하기를 좋아하기 때문에 실제로는 질문과 관련이 없습니다.
jmoreno

26

최종 결과를 담을 변수를 선택하여 선택하십시오.

가장 쉬운 솔루션

DECLARE @char VARCHAR(MAX);

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

PRINT @char;

25

PostgreSQL 9.0부터는 매우 간단합니다.

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

9.0 이전의 버전에서는 array_agg()hgmnz로 표시된대로 사용할 수 있습니다.


텍스트 유형이 아닌 열로이를 수행하려면 유형 캐스트를 추가해야합니다.SELECT string_agg(non_text_type::text, ',') FROM table
Torben Kohlmeier

@TorbenKohlmeier : 문자가 아닌 열 (예 : 정수, 소수)에만 필요합니다. 그것은을 위해 잘 작동 varchar또는char
a_horse_with_no_name


18

XML을 사용하면 행을 쉼표로 구분하는 데 도움이되었습니다. 여분의 쉼표로 SQL Server의 바꾸기 기능을 사용할 수 있습니다. 쉼표를 추가하는 대신 AS 'data ()'를 사용하면 행이 공백으로 연결되며 나중에이 구문은 쉼표로 대체 될 수 있습니다.

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

2
이것은 내 의견에 가장 적합한 답변입니다. 다른 테이블에서 조인해야 할 때 선언 변수를 사용하는 것은 좋지 않으며 이는 훌륭하고 짧습니다. 잘 했어.
David Roussel

7
FName 데이터에 공백이 이미 있으면 제대로 작동하지 않습니다 (예 : "My Name"
binball

실제로 그것은 ms-sql 2016에서 나를 위해 일하고 있습니다. , ') allBrands로
Rejwanul Reja

17

추가 쉼표없이 바로 사용할 수있는 솔루션 :

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

빈 목록은 NULL 값이됩니다. 일반적으로 목록을 테이블 열 또는 프로그램 변수에 삽입합니다. 필요에 따라 255 최대 길이를 조정하십시오.

Diwakar와 Jens Frandsen은 좋은 답변을 제공했지만 개선이 필요합니다.


이것을 사용할 때 쉼표 앞에 공백이 있습니다 :(
slayernoah

1
그냥 교체 ', '와 함께 ','당신이 여분의 공간을하지 않으려면.
Daniel Reis

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

샘플은 다음과 같습니다.

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

10
DECLARE @Names VARCHAR(8000)
SELECT @name = ''
SELECT @Names = @Names + ',' + Names FROM People
SELECT SUBSTRING(2, @Names, 7998)

이렇게하면 시작 부분에 쉼표가 표시됩니다.

그러나 다른 열이 필요하거나 하위 테이블을 CSV로 만들려면이를 스칼라 사용자 정의 필드 (UDF)로 랩핑해야합니다.

SELECT 절에서 XML 경로를 상관 하위 쿼리로 사용할 수도 있습니다 (그러나 Google은 집에서 일을하지 않기 때문에 다시 일할 때까지 기다려야합니다 :-)


10

다른 답변의 경우 답변을 읽는 사람은 차량 또는 학생과 같은 특정 도메인 테이블을 알고 있어야합니다. 솔루션을 테스트하려면 테이블을 작성하고 데이터로 채워야합니다.

아래는 SQL Server "Information_Schema.Columns"테이블을 사용하는 예입니다. 이 솔루션을 사용하면 테이블을 만들거나 데이터를 추가 할 필요가 없습니다. 이 예는 데이터베이스의 모든 테이블에 대해 쉼표로 구분 된 열 이름 목록을 작성합니다.

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 

7

Oracle DB의 경우이 질문을 참조하십시오 . 저장 프로 시저를 작성하지 않고 Oracle에서 여러 행을 하나로 연결할 수 있습니까?

@Emmanuel이 Oracle 11g Release 2 이상에서 사용할 수있는 내장 LISTAGG () 함수를 사용하는 것이 가장 좋습니다.

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

@ user762952가 지적했듯이 오라클의 문서 http://www.oracle-base.com/articles/misc/string-aggregation-techniques.php 에 따르면 에 따르면 WM_CONCAT () 함수도 옵션입니다. 안정된 것처럼 보이지만 Oracle은 명시 적으로 응용 프로그램 SQL에 사용하지 않는 것이 좋으므로 위험 부담으로 사용하십시오.

그 외에는 자신의 기능을 작성해야합니다. 위의 Oracle 문서에는이를 수행하는 방법에 대한 안내서가 있습니다.


7

null 값을 피하기 위해 CONCAT ()를 사용할 수 있습니다

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

CONCAT이 작동하는 이유 를 아는 것이 좋습니다 . MSDN에 대한 링크가 좋을 것입니다.
리버스 엔지니어

7

나는 Dana의 대답의 우아함을 정말로 좋아했습니다 . 그냥 완성하고 싶었습니다.

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

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

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

마지막 두 기호 ','를 삭제하는 경우 이름 뒤에 ','를 추가해야합니다 ( 'SELECT \ @names = \ @names + Name +', 'FROM Names'). 그렇게하면 마지막 두 문자는 항상 ','가됩니다.
JT_

필자의 경우 선행 쉼표를 제거해야 하므로 쿼리를 변경 한 SELECT @names = @names + CASE WHEN LEN(@names)=0 THEN '' ELSE ', ' END + Name FROM Names다음 나중에 잘리지 않아도됩니다.
Tian van Heerden

6

이 답변을 사용하려면 서버에서 일부 권한이 필요합니다.

어셈블리 는 좋은 옵션입니다. 작성 방법을 설명하는 사이트가 많이 있습니다. 나는 아주 잘 설명되어 생각 하나는 이것이다 하나

원하는 경우 이미 어셈블리를 만들었으며 여기 에서 DLL을 다운로드 할 수 있습니다 .

다운로드 한 후에는 SQL Server에서 다음 스크립트를 실행해야합니다.

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

서버가 어셈블리 경로에 액세스 할 수 있는지 확인하십시오. 모든 단계를 성공적으로 완료 했으므로 다음과 같은 기능을 사용할 수 있습니다.

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

도움이 되길 바랍니다 !!!


1
DLL 링크는 404 오류입니다. 이를 위해 어셈블리를 사용하는 것은 과잉입니다. SQL Server에 대한 최상의 답변 을 참조하십시오 .
인접

6

MySQL 완전한 예 :

우리는 많은 데이터를 가질 수있는 사용자를 가지고 있으며 모든 사용자 데이터를 목록에서 볼 수있는 출력을 원합니다.

결과:

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

테이블 설정 :

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);

질문:

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

일반적으로 SQL Server에서 문자열을 연결하기 위해 다음과 같이 select를 사용합니다.

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

5

널 (null)을 처리하려면 where 절을 추가하거나 첫 번째 항목 주위에 다른 COALESCE를 추가하여이를 수행 할 수 있습니다.

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

5

이것은 나를 위해 일했습니다 ( SqlServer 2016 ).

SELECT CarNamesString = STUFF((
         SELECT ',' + [Name]
            FROM tbl_cars 
            FOR XML PATH('')
         ), 1, 1, '')

여기 소스가 있습니다 : https://www.mytecbits.com/

그리고 MySql에 대한 솔루션 (이 페이지는 MySql 용 Google에 표시되므로)

SELECT [Name],
       GROUP_CONCAT(DISTINCT [Name]  SEPARATOR ',')
       FROM tbl_cars

에서 MySQL의 자료 문서



4

이것도 유용 할 수 있습니다

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

보고

Peter,Paul,Mary

5
불행히도이 동작은 공식적으로 지원되지 않는 것 같습니다. MSDN 은 "변수가 선택 목록에서 참조되면 스칼라 값이 지정되거나 SELECT 문이 하나의 행만 반환해야합니다"라고 말합니다. 그리고 문제를 관찰 한 사람들이 있습니다 : sqlmag.com/sql-server/multi-row-variable-assignment-and-order
blueling
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.