it-swarm-korea.com

임시 물품과 'Xml 경로'SQL Server에서 작동

표 :

+----+------+
| Id | Name |
+----+------+    
| 1  | aaa  |
| 1  | bbb  |
| 1  | ccc  |
| 1  | ddd  |
| 1  | eee  |
+----+------+

필수 출력 :

+----+---------------------+
| Id |        abc          |
+----+---------------------+ 
|  1 | aaa,bbb,ccc,ddd,eee |
+----+---------------------+

질문:

SELECT ID, 
    abc = STUFF(
                 (SELECT ',' + name FROM temp1 FOR XML PATH ('')), 1, 1, ''
               ) 
FROM temp1 GROUP BY id

이 쿼리는 제대로 작동하고 있습니다. 그러나 나는 그것이 작동하는 방법에 대한 설명이 필요하거나 이것을 할 수있는 다른 방법이나 짧은 방법이 있습니다.

나는 이것을 이해하기 매우 혼란스러워진다.

268
Puneet Chawla

작동 방식은 다음과 같습니다.

1. FOR XML로 XML 요소 문자열 가져 오기

FOR XML PATH를 질의 끝에 추가하면 PATH 인수에 요소 이름이 포함 된 XML 요소로 쿼리 결과를 출력 할 수 있습니다. 예를 들어, 다음 명령문을 실행하는 경우 :

SELECT ',' + name 
              FROM temp1
              FOR XML PATH ('')

공백 문자열 (FOR XML PATH ( ''))을 전달하면 대신 다음과 같이 표시됩니다.

,aaa,bbb,ccc,ddd,eee

2. STUFF로 선행 쉼표 제거

STUFF 문은 하나의 문자열을 다른 문자열에 "채우는"것으로, 첫 번째 문자열 내의 문자를 대체합니다. 그러나 결과 값 목록의 첫 번째 문자를 제거하기 위해 단순히 사용합니다.

SELECT abc = STUFF((
            SELECT ',' + NAME
            FROM temp1
            FOR XML PATH('')
            ), 1, 1, '')
FROM temp1

STUFF의 매개 변수는 다음과 같습니다.

  • "채워질 문자열"(우리의 경우 쉼표로 된 전체 이름 목록)
  • 문자 삭제 및 삽입을 시작할 위치 (1, 빈 문자열에 채우기)
  • 삭제할 문자 수 (1, 선행 쉼표)

그래서 우리는 결국 :

aaa,bbb,ccc,ddd,eee

3. ID에 가입하여 전체 목록을 얻으십시오.

다음으로 우리는 임시 테이블에있는 id의 목록에이 이름을 결합하여 ID가있는 이름 목록을 얻습니다.

SELECT ID,  abc = STUFF(
             (SELECT ',' + name 
              FROM temp1 t1
              WHERE t1.id = t2.id
              FOR XML PATH (''))
             , 1, 1, '') from temp1 t2
group by id;

그리고 우리는 우리의 결과를 가지고 있습니다 :

-----------------------------------
| Id        | Name                |
|---------------------------------|
| 1         | aaa,bbb,ccc,ddd,eee |
-----------------------------------

희망이 도움이!

536
FutbolFan

이 기사 는 연결된 값을 XML 인코딩하지 않는 향상된 코드 버전을 비롯하여 SQL에서 문자열을 연결하는 다양한 방법을 다룹니다.

SELECT ID, abc = STUFF
(
    (
        SELECT ',' + name
        FROM temp1 As T2
        -- You only want to combine rows for a single ID here:
        WHERE T2.ID = T1.ID
        ORDER BY name
        FOR XML PATH (''), TYPE
    ).value('.', 'varchar(max)')
, 1, 1, '')
FROM temp1 As T1
GROUP BY id

무슨 일이 일어나고 있는지 이해하려면 내부 쿼리로 시작하십시오.

SELECT ',' + name
FROM temp1 As T2
WHERE T2.ID = 42 -- Pick a random ID from the table
ORDER BY name
FOR XML PATH (''), TYPE

FOR XML를 지정하기 때문에 모든 행을 나타내는 XML 조각이 포함 된 단일 행을 가져옵니다.

첫 번째 열에 대해 열 별칭을 지정하지 않았으므로 각 행은 FOR XML PATH 다음에 대괄호로 지정된 이름으로 XML 요소에 래핑됩니다. 예를 들어 FOR XML PATH ('X')을 사용했다면 다음과 같은 XML 문서를 얻을 수 있습니다.

<X>,aaa</X>
<X>,bbb</X>
...

그러나 요소 이름을 지정하지 않았으므로 값 목록 만 얻을 수 있습니다.

,aaa,bbb,...

.value('.', 'varchar(max)')은 단순히 "특수"문자를 XML 인코딩하지 않고 결과 XML 조각에서 값을 검색합니다. 이제 다음과 같은 문자열이 있습니다.

',aaa,bbb,...'

STUFF 함수는 선행 쉼표를 제거하여 다음과 같은 최종 결과를 제공합니다.

'aaa,bbb,...'

언뜻 보면 꽤 혼란스러워 보일 지 모르지만, 다른 옵션들에 비해 꽤 잘 수행되는 경향이 있습니다.

62
Richard Deeming

PATH 모드는 SELECT 쿼리에서 XML을 생성하는 데 사용됩니다.

1. SELECT   
       ID,  
       Name  
FROM temp1
FOR XML PATH;  

Ouput:
<row>
<ID>1</ID>
<Name>aaa</Name>
</row>

<row>
<ID>1</ID>
<Name>bbb</Name>
</row>

<row>
<ID>1</ID>
<Name>ccc</Name>
</row>

<row>
<ID>1</ID>
<Name>ddd</Name>
</row>

<row>
<ID>1</ID>
<Name>eee</Name>
</row>

출력은 결과 행 집합의 각 열 값이 행 요소에 래핑되는 요소 중심 XML입니다. SELECT 절은 C 럼 이름에 대해 별명을 지정하지 않으므로 생성 된 하위 요소 이름은 SELECT 절의 해당 C 럼 이름과 같습니다.

행 집합의 각 행에 대해 태그가 추가됩니다.

2.
SELECT   
       ID,  
       Name  
FROM temp1
FOR XML PATH('');

Ouput:
<ID>1</ID>
<Name>aaa</Name>
<ID>1</ID>
<Name>bbb</Name>
<ID>1</ID>
<Name>ccc</Name>
<ID>1</ID>
<Name>ddd</Name>
<ID>1</ID>
<Name>eee</Name>

2 단계의 경우 : 길이가 0 인 문자열을 지정하면 랩핑 요소가 작성되지 않습니다.

3. 

    SELECT   

           Name  
    FROM temp1
    FOR XML PATH('');

    Ouput:
    <Name>aaa</Name>
    <Name>bbb</Name>
    <Name>ccc</Name>
    <Name>ddd</Name>
    <Name>eee</Name>

4. SELECT   
        ',' +Name  
FROM temp1
FOR XML PATH('')

Ouput:
,aaa,bbb,ccc,ddd,eee

4 단계에서는 값을 연결합니다.

5. SELECT ID,
    abc = (SELECT   
            ',' +Name  
    FROM temp1
    FOR XML PATH('') )
FROM temp1

Ouput:
1   ,aaa,bbb,ccc,ddd,eee
1   ,aaa,bbb,ccc,ddd,eee
1   ,aaa,bbb,ccc,ddd,eee
1   ,aaa,bbb,ccc,ddd,eee
1   ,aaa,bbb,ccc,ddd,eee


6. SELECT ID,
    abc = (SELECT   
            ',' +Name  
    FROM temp1
    FOR XML PATH('') )
FROM temp1 GROUP by iD

Ouput:
ID  abc
1   ,aaa,bbb,ccc,ddd,eee

6 단계에서 ID를 기준으로 날짜를 그룹화합니다.

STUFF (source_string, start, length, add_string) E 개/수 또는 인수 source_string 수정할 소스. 자열. start 길이 문자를 삭제할 source_string의 위치를 ​​입력 한 다음 add_string을 삽입하십시오. length source_string에서 h 제할. 자 수. add_string 시작 위치에서 source_string에 삽입 할 문자 시퀀스입니다.

SELECT ID,
    abc = 
    STUFF (
        (SELECT   
                ',' +Name  
        FROM temp1
        FOR XML PATH('')), 1, 1, ''
    )
FROM temp1 GROUP by iD

Output:
-----------------------------------
| Id        | Name                |
|---------------------------------|
| 1         | aaa,bbb,ccc,ddd,eee |
-----------------------------------
30
Neha Chopra

이 정확한 시나리오를 처리하기 위해 Azure SQL Database와 SQL Server (2017로 시작)에 새로운 기능이 추가되었습니다. 나는 이것이 당신이 XML/STUFF 방법으로 달성하려고 시도하는 것에 대한 네이티브 공식 방법으로 작용할 것이라고 믿는다. 예:

select id, STRING_AGG(name, ',') as abc
from temp1
group by id

STRING_AGG - https://msdn.Microsoft.com/en-us/library/mt790580.aspx

EDIT : 내가 처음 게시했을 때 SQL Server 2016에 대한 언급이있었습니다. 잠재적 인 기능이 포함되어 있다고 생각했기 때문입니다. 어느 쪽이 잘못되었거나 뭔가 바뀌 었는지, 버전을 수정하는 제안 된 수정에 감사드립니다. 또한 꽤 인상 깊었고 마지막 옵션을 위해 나를 끌어 들인 다중 단계 검토 프로세스를 완전히 알지 못했습니다.

16
Brian Jorden

for xml path에서 [ for xml path('ENVLOPE') ]과 같은 값을 정의하면 이러한 태그가 각 행에 추가됩니다.

<ENVLOPE>
</ENVLOPE>
3
vikas
SELECT ID, 
    abc = STUFF(
                 (SELECT ',' + name FROM temp1 FOR XML PATH ('')), 1, 1, ''
               ) 
FROM temp1 GROUP BY id

위 쿼리에서 STUFF 함수는 생성 된 XML 문자열 (,)에서 첫 번째 쉼표 (,aaa,bbb,ccc,ddd,eee)를 제거하는 데 사용됩니다. 그러면 (aaa,bbb,ccc,ddd,eee)가됩니다.

그리고 FOR XML PATH('')은 단순히 열 데이터를 (,aaa,bbb,ccc,ddd,eee) 문자열로 변환하지만 PATH에서는 전달하는 ''태그이므로 XML 태그를 만들지 않습니다.

마지막에는 ID column을 사용하여 레코드를 그룹화했습니다.

2
Declare @Temp As Table (Id Int,Name Varchar(100))
Insert Into @Temp values(1,'A'),(1,'B'),(1,'C'),(2,'D'),(2,'E'),(3,'F'),(3,'G'),(3,'H'),(4,'I'),(5,'J'),(5,'K')
Select X.ID,
stuff((Select ','+ Z.Name from @Temp Z Where X.Id =Z.Id For XML Path('')),1,1,'')
from @Temp X
Group by X.ID
1
Omkar Naik

디버깅을 마침내 내 '채워진'쿼리를 정상적인 방법으로 반환했습니다.

간단히

select * from myTable for xml path('myTable')

내가 테이블 디버깅에서 로그 테이블에 쓸 테이블의 내용을 제공합니다.

1
SlavaTT