Pun*_*wla 320 sql database sql-server
表是:
+----+------+
| Id | Name |
+----+------+
| 1 | aaa |
| 1 | bbb |
| 1 | ccc |
| 1 | ddd |
| 1 | eee |
+----+------+
Run Code Online (Sandbox Code Playgroud)
所需输出:
+----+---------------------+
| Id | abc |
+----+---------------------+
| 1 | aaa,bbb,ccc,ddd,eee |
+----+---------------------+
Run Code Online (Sandbox Code Playgroud)
查询:
SELECT ID,
abc = STUFF(
(SELECT ',' + name FROM temp1 FOR XML PATH ('')), 1, 1, ''
)
FROM temp1 GROUP BY id
Run Code Online (Sandbox Code Playgroud)
此查询正常运行.但我只需要解释它是如何工作的,或者是否有其他或简短的方法来做到这一点.
我很难理解这一点.
Fut*_*Fan 613
下面是它的工作原理:
1.使用FOR XML获取XML元素字符串
将FOR XML PATH添加到查询末尾允许您将查询结果作为XML元素输出,其中元素名称包含在PATH参数中.例如,如果我们要运行以下语句:
SELECT ',' + name
FROM temp1
FOR XML PATH ('')
Run Code Online (Sandbox Code Playgroud)
通过传入一个空字符串(FOR XML PATH('')),我们得到以下内容:
,aaa,bbb,ccc,ddd,eee
Run Code Online (Sandbox Code Playgroud)
2.删除STUFF的前导逗号
STUFF语句实际上将一个字符串"填充"到另一个字符串中,替换第一个字符串中的字符.但是,我们只是使用它来删除结果值列表的第一个字符.
SELECT abc = STUFF((
SELECT ',' + NAME
FROM temp1
FOR XML PATH('')
), 1, 1, '')
FROM temp1
Run Code Online (Sandbox Code Playgroud)
参数STUFF是:
所以我们最终得到:
aaa,bbb,ccc,ddd,eee
Run Code Online (Sandbox Code Playgroud)
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;
Run Code Online (Sandbox Code Playgroud)
我们得到了结果:
-----------------------------------
| Id | Name |
|---------------------------------|
| 1 | aaa,bbb,ccc,ddd,eee |
-----------------------------------
Run Code Online (Sandbox Code Playgroud)
希望这可以帮助!
Ric*_*ing 67
本文介绍了在SQL中连接字符串的各种方法,包括代码的改进版本,它不对连接值进行XML编码.
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
Run Code Online (Sandbox Code Playgroud)
要了解发生了什么,请从内部查询开始:
SELECT ',' + name
FROM temp1 As T2
WHERE T2.ID = 42 -- Pick a random ID from the table
ORDER BY name
FOR XML PATH (''), TYPE
Run Code Online (Sandbox Code Playgroud)
因为您正在指定FOR XML,所以您将获得包含表示所有行的XML片段的单行.
因为您没有为第一列指定列别名,所以每行都将包装在XML元素中,并在后面的括号中指定名称FOR XML PATH.例如,如果有FOR XML PATH ('X'),您将获得一个类似于以下内容的XML文档:
<X>,aaa</X>
<X>,bbb</X>
...
Run Code Online (Sandbox Code Playgroud)
但是,由于您尚未指定元素名称,因此您只需获取值列表:
,aaa,bbb,...
Run Code Online (Sandbox Code Playgroud)
它.value('.', 'varchar(max)')只是从生成的XML片段中检索值,而不对任何"特殊"字符进行XML编码.你现在有一个看起来像这样的字符串:
',aaa,bbb,...'
Run Code Online (Sandbox Code Playgroud)
该STUFF函数然后删除前导逗号,给出最终结果,如下所示:
'aaa,bbb,...'
Run Code Online (Sandbox Code Playgroud)
乍一看看起来很混乱,但与其他一些选项相比,它确实表现得相当不错.
Neh*_*pra 39
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>
Run Code Online (Sandbox Code Playgroud)
Output是以元素为中心的XML,其中生成的行集中的每个列值都包含在一个行元素中.由于SELECT子句未指定列名的任何别名,因此生成的子元素名称与SELECT子句中的相应列名称相同.
对于行集中的每一行,都会添加一个标记.
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>
Run Code Online (Sandbox Code Playgroud)
对于步骤2:如果指定零长度字符串,则不会生成包装元素.
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
Run Code Online (Sandbox Code Playgroud)
在第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
Run Code Online (Sandbox Code Playgroud)
在第6步中,我们按ID对日期进行分组.
STUFF(source_string,start,length,add_string)参数或参数source_string要修改的源字符串.start source_string中的位置以删除长度字符,然后插入add_string.length要从source_string中删除的字符数.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 |
-----------------------------------
Run Code Online (Sandbox Code Playgroud)
Bri*_*den 17
Azure SQL数据库和SQL Server(从2017年开始)中有非常新的功能来处理这种确切的情况.我相信这将成为您尝试使用XML/STUFF方法完成的本地官方方法.例:
select id, STRING_AGG(name, ',') as abc
from temp1
group by id
Run Code Online (Sandbox Code Playgroud)
STRING_AGG - https://msdn.microsoft.com/en-us/library/mt790580.aspx
编辑:当我最初发布这个时,我提到了SQL Server 2016,因为我认为我看到了一个潜在的功能,包括在内.要么我记得错误或改变了某些东西,感谢建议编辑修复版本.此外,令人印象深刻,并没有充分意识到多步审查过程,只是拉我进入最后的选择.
小智 5
在中for xml path,如果我们定义任何类似的值,[ for xml path('ENVLOPE') ]则这些标记将与每一行一起添加:
<ENVLOPE>
</ENVLOPE>
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
450113 次 |
| 最近记录: |