簡體   English   中英

這個查詢創建逗號分隔列表SQL Server的作用是什么?

[英]What this query does to create comma delimited list SQL Server?

我在google的幫助下編寫了這個查詢,從表中創建了一個分隔列表,但我對此查詢沒有任何理解。

任何人都可以解釋我發生了什么

 SELECT 
    E1.deptno, 
    allemp = Replace ((SELECT E2.ename AS 'data()' 
                       FROM emp AS e2 
                       WHERE e1.deptno = e2.DEPTNO 
                       FOR xml PATH('')), ' ', ', ') 
 FROM EMP AS e1 
 GROUP BY DEPTNO; 

給我結果

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

解釋它的最簡單方法是查看FOR XML PATH如何為實際XML工作。 想象一個簡單的表Employee

EmployeeID      Name
1               John Smith
2               Jane Doe

你可以用

SELECT  EmployeeID, Name
FROM    emp.Employee
FOR XML PATH ('Employee')

這將創建XML如下

<Employee>
    <EmployeeID>1</EmployeeID>
    <Name>John Smith</Name>
</Employee>
<Employee>
    <EmployeeID>2</EmployeeID>
    <Name>Jane Doe</Name>
</Employee>

PATH刪除“Employee”會刪除外部xml標記,因此此查詢:

SELECT  Name
FROM    Employee
FOR XML PATH ('')

會創造

    <Name>John Smith</Name>
    <Name>Jane Doe</Name>

您正在做的事情並不理想,列名'data()'強制sql錯誤,因為它試圖創建一個不合法標記的xml標記,因此會生成以下錯誤:

列名'Data()'包含FOR XML所需的無效XML標識符; '('(0x0028)是第一個出錯的角色。

相關子查詢隱藏此錯誤,只生成沒有標記的XML:

SELECT  Name AS [Data()]
FROM    Employee
FOR XML PATH ('')

創建

John Smith Jane Doe

然后你用逗號替換空格,相當自我解釋......

如果我是你,我會略微調整查詢:

SELECT  E1.deptno, 
        STUFF(( SELECT  ', ' + E2.ename 
                FROM    emp AS e2 
                WHERE   e1.deptno = e2.DEPTNO 
                FOR XML PATH('')
            ), 1, 2, '') 
FROM    EMP AS e1 
GROUP BY DEPTNO; 

沒有列別名將意味着沒有創建xml標記,並且在select查詢中添加逗號意味着任何帶有空格的名稱都不會導致錯誤, STUFF將刪除第一個逗號和空格。

附錄

要詳細說明知識管理在評論中所說的內容,因為這似乎會獲得更多視圖,轉義XML字符的正確方法是使用.value ,如下所示:

SELECT  E1.deptno, 
        STUFF(( SELECT  ', ' + E2.ename 
                FROM    emp AS e2 
                WHERE   e1.deptno = e2.DEPTNO 
                FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)'), 1, 2, '') 
FROM    EMP AS e1 
GROUP BY DEPTNO; 

從內到外逐步分開。

步驟1:

運行最里面的查詢並查看它產生的內容:

SELECT E2.ename AS 'data()' 
FROM emp AS e2 
WHERE e2.DEPTNO = 10
FOR XML PATH('')

你應該得到一個類似的輸出:

CLARK KING MILLER

第2步:

REPLACE剛剛替換用的空間, -從而把您的輸出入

CLARK, KING, MILLER

第3步:

外部查詢獲取deptno值 - 加上內部查詢的結果 - 並生成最終結果。

使用新的STRING_AGG SQL Server 2017使這一過程變得更加容易。 最近遇到這篇文章並將我的STUFF / FOR XML策略切換為使用新的字符串函數。 還避免了需要額外的JOIN / SUBQUERY和FOR XML的開銷( 以及奇數編碼問題 )並且難以解釋SQL。

SELECT  E1.deptno, 
        STRING_AGG(E1.ename, ', ') AS allemp
FROM    EMP AS e1 
GROUP BY DEPTNO; 

注意 :另外請務必查看對應的STRING_SPLIT ,以便更輕松地使用SQL分隔數據。

外部查詢檢索部門編號列表,然后為每個部門編號運行子查詢以返回屬於該部門的所有名稱。 子查詢使用FOR XML語句將輸出格式化為單行逗號分隔列表。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM