Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
此查询如何创建逗号分隔的SQL Server列表?_Sql_Sql Server_Sql Server 2008 - Fatal编程技术网

此查询如何创建逗号分隔的SQL Server列表?

此查询如何创建逗号分隔的SQL Server列表?,sql,sql-server,sql-server-2008,Sql,Sql Server,Sql Server 2008,我在google的帮助下编写了这个查询,从一个表中创建了一个带分隔符的列表,但我不理解这个查询中的任何内容 谁能解释一下发生了什么事 SELECT E1.deptno, allemp = Replace ((SELECT E2.ename AS 'data()' FROM emp AS e2 WHERE e1.deptno = e2.DEPTNO

我在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语句将输出格式化为一行逗号分隔的列表。

将其从内到外逐步分解

第1步:

运行最内部的查询并查看其生成的内容:

SELECT E2.ename AS 'data()' 
FROM emp AS e2 
WHERE e2.DEPTNO = 10
FOR XML PATH('')
您应该得到如下输出:

CLARK KING MILLER
第二步:

REPLACE
仅将空格替换为
——从而将输出转换为

CLARK, KING, MILLER
第三步:


外部查询获取
deptno
值,加上内部查询的结果,并生成最终结果。

解释它的最简单方法是查看
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>
会创造

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

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
将删除第一个逗号和空格

附录

为了详细说明KM在评论中所说的话,因为这似乎获得了更多的视图,转义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; 

SQL Server 2017使这一过程变得更加简单。最近我看到了这篇文章,将我的STUFF/FOR XML策略改为使用新的字符串函数。还避免了额外的连接/子查询,避免了XML的开销(以及奇怪的编码问题)和难以解释的SQL

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

注意:还要确保更轻松地使用SQL分隔的数据

请注意,对于包含字符的文本,您的代码将失败,如><&您将获得字符扩展,如&有一种更好的方法来实现这种连接,请参见:+1良好的解释,但请注意,对于包含字符的文本,此代码将失败,如><&您将获得字符扩展,如
&
有一种更好的方法来实现这种连接,请参见:您缺少一个引号来结束
'NVARCHAR(MAX)
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; 
SELECT  E1.deptno, 
        STRING_AGG(E1.ename, ', ') AS allemp
FROM    EMP AS e1 
GROUP BY DEPTNO;