본문 바로가기

SQL Server/SQL Server Tip & Tech

FOR XML PATH Concatenation을 사용하는 재치있는 방법

FOR XML PATH 를 사용해서 서로 다른 Row에 있는 문자열을 하나로 합치는 팁.

예를 들어... 원본 테이블이 아래와 같고

a b c
1 1
2 1
3 1
4 2
5 2
6 3

원하는 결과는 아래와 같다고 할때,
b c
1 가,나,다
2 라,마
3

FOR XML PAHT상관 서브 쿼리를 사용하면 아래 쿼리 한번으로 결과를 얻을 수 있다.

1
2
3
4
5
6
7
8
SELECT b, STUFF((
    SELECT N',' + c
    FROM sourceTable
    WHERE b = st1.b
    FOR XML PATH('')
  ), 11, N'') AS c
FROM sourceTable st1
GROUP BY b;
cs


좀 더 실전적인 예제 : SQL Server magazine 2008.07 p.10에서 가져옴

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
USE AdventureWorks
GO
 
SELECT
  vfs.database_id,
  DBName = DB_NAME(vfs.database_id),
  DB_Reads = SUM(vfs.num_of_reads),
  DB_Writes = SUM(vfs.num_of_writes),
  DB_BytesRead = SUM(num_of_bytes_read),
  DB_IOStallReadMS = SUM(io_stall_read_ms),
  DB_BytesWritten = SUM(num_of_bytes_written),
  DB_IOStallWriteMS = SUM(io_stall_write_ms),
  DB_IOStall = SUM(io_stall),
  DB_BytesSize = SUM(size_on_disk_bytes),
  DB_Files = dt.file_list
FROM sys.dm_io_virtual_file_stats(NULLNULL) vfs
  INNER JOIN (
    SELECT
      vfs2.database_id,
      STUFF((
        SELECT ',' + mf3.name AS [text()]
        FROM sys.dm_io_virtual_file_stats(NULLNULL) vfs3
          INNER JOIN sys.master_files mf3
            ON mf3.database_id = vfs3.database_id
              AND mf3.file_id = vfs3.file_id
        WHERE vfs2.database_id = vfs3.database_id
        FOR XML PATH('')), 11'') AS file_list
    FROM sys.dm_io_virtual_file_stats(NULLNULL) vfs2
      INNER JOIN sys.master_files mf2 ON mf2.database_id = vfs2.database_id
    GROUP BY vfs2.database_id, DB_NAME(vfs2.database_id)
  ) dt ON dt.database_id = vfs.database_id
GROUP BY vfs.database_id, DB_NAME(vfs.database_id), dt.file_list
ORDER BY DB_NAME(vfs.database_id)
cs