Koe*_*oen 17 sql t-sql sql-server sqlxml
我正在使用通用系统进行报告,该系统从数据库视图中获取数据(SQL Server 2005).在这个视图中,我必须在一行中合并一对多关系中的数据,并在此线程中使用priyanka.sarkar描述的解决方案:将子查询中的多个结果合并为一个逗号分隔值.该解决方案使用SQLXML来合并数据(子查询):
SELECT STUFF(
( SELECT ', ' + Name
FROM MyTable _in
WHERE _in.ID = _out.ID
FOR XML PATH('')), -- Output multiple rows as one xml type value,
-- without xml tags
1, 2, '') -- STUFF: Replace the comma at the beginning with empty string
FROM MyTable _out
GROUP BY ID -- Removes duplicates
Run Code Online (Sandbox Code Playgroud)
这完全有效(它甚至没有那么重的性能),除了我的数据现在& 通过SQLXML 进行XML编码(&=> 等) - 毕竟我不想要XML数据,我只是用它作为一个技巧 - 因为通用系统我无法对此进行编码以清理它,因此编码数据直接进入报告.我不能在通用系统中使用存储过程,因此CURSOR-merge或COALESCE-ing不是一个选项......
所以我正在寻找的是T-SQL中的一种方式,它允许我再次解码XML,甚至更好:避免SQLXML对其进行编码.显然我可以编写一个存储函数来执行此操作,但我更喜欢内置,更安全的方式...
谢谢你的帮助...
dot*_*joe 22
(
select ...
from t
for xml path(''), type
).value('.', 'nvarchar(max)')
Run Code Online (Sandbox Code Playgroud)
如果指定type为选项for xml,则可以使用XPath查询将XML类型转换回a varchar.使用示例表变量:
declare @MyTable table (id int, name varchar(50))
insert @MyTable (id, name) select 1, 'Joel & Jeff'
union all select 1, '<<BIN LADEN>>'
union all select 2, '&&BUSH&&'
Run Code Online (Sandbox Code Playgroud)
一种可能的解决方案是
select b.txt.query('root').value('.', 'varchar(max)')
from (
select distinct id
from @MyTable
) a
cross apply
(
select CASE ROW_NUMBER() OVER(ORDER BY id) WHEN 1 THEN ''
ELSE ', ' END + name
from @MyTable
where id = a.id
order by
id
for xml path(''), root('root'), type
) b(txt)
Run Code Online (Sandbox Code Playgroud)
这将打印:
Joel & Jeff, <<BIN LADEN>>
&&BUSH&&
Run Code Online (Sandbox Code Playgroud)
这是没有XML转换的替代方案.它确实有一个递归查询,因此性能里程可能会有所不同.这是来自Quassnoi的博客:
;WITH with_stats(id, name, rn, cnt) AS
(
SELECT id, name,
ROW_NUMBER() OVER (PARTITION BY id ORDER BY name),
COUNT(*) OVER (PARTITION BY id)
FROM @MyTable
),
with_concat (id, name, gc, rn, cnt) AS
(
SELECT id, name,
CAST(name AS VARCHAR(MAX)), rn, cnt
FROM with_stats
WHERE rn = 1
UNION ALL
SELECT with_stats.id, with_stats.name,
CAST(with_concat.gc + ', ' + with_stats.name AS VARCHAR(MAX)),
with_stats.rn, with_stats.cnt
FROM with_concat
JOIN with_stats
ON with_stats.id = with_concat.id
AND with_stats.rn = with_concat.rn + 1
)
SELECT id, gc
FROM with_concat
WHERE rn = cnt
OPTION (MAXRECURSION 0)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
9298 次 |
| 最近记录: |