【问题标题】:Convert STRING_AGG to FOR XML PATH将 STRING_AGG 转换为 FOR XML PATH
【发布时间】:2020-04-06 19:19:49
【问题描述】:

我有一个带有嵌套选择的查询。我在 SQL Server 2017 中编写了此查询,现在我必须将其转换为在 SQL Server 2014 中使用。我知道STRING_AGG 必须转换为FOR XML PATHSTUFF,我尝试了某种类型的查询,但我不能找到答案。

SQL Server 2017 中的原始工作查询是:

SELECT filesanadrow, STRING_AGG(CONVERT(nvarchar(MAX),result.tarafhesabsharh), ' ; ') AS tarafhesabha
FROM (SELECT DISTINCT k.row AS filesanadrow, CONVERT(NVARCHAR(MAX), t.tarafhesabsharh) AS tarafhesabsharh
FROM filesanad AS k INNER JOIN tarafhesab AS t ON k.row = t.filesanadrow) AS result
GROUP BY filesanadrow

然后STRING_AGG(CONVERT(nvarchar(MAX),result.tarafhesabsharh), ' ; ') 必须转换为 FOR XML PATH 和 STUFF。

我试过这段代码:

SELECT filesanadrow,
STUFF((SELECT distinct '' + t2.tarafhesabsharh
from result t2 where t1.filesanadrow = t2.filesanadrow 
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'),1,0,'') AS tarafhesabha
FROM (SELECT DISTINCT k.row AS filesanadrow, CONVERT(NVARCHAR(MAX), t.tarafhesabsharh) AS tarafhesabsharh
FROM filesanad AS k INNER JOIN tarafhesab AS t ON k.row = t.filesanadrow) AS result
GROUP BY filesanadrow 

但是 SQL Server 返回:

(无效的对象名'result'。SQL2.sql 3 1)

我也试过了:

SELECT filesanadrow,
STUFF((SELECT '; ' + name FROM result  FOR XML PATH('')), 1, 1, '') AS tarafhesabha
FROM (SELECT DISTINCT k.row AS filesanadrow, CONVERT(NVARCHAR(MAX), t.tarafhesabsharh) AS tarafhesabsharh
FROM filesanad AS k INNER JOIN tarafhesab AS t ON k.row = t.filesanadrow) AS result
GROUP BY filesanadrow

但是 SQL Server 返回:

对象名称“结果”无效。 SQL2.sql 2 1

我又试了一次:

SELECT filesanadrow,
STUFF((SELECT '; ' + tarafhesabsharh FROM tarafhesab  FOR XML PATH('')), 1, 1, '') AS tarafhesabha
FROM (SELECT DISTINCT k.row AS filesanadrow, CONVERT(NVARCHAR(MAX), t.tarafhesabsharh) AS tarafhesabsharh
FROM filesanad AS k INNER JOIN tarafhesab AS t ON k.row = t.filesanadrow) AS result
GROUP BY filesanadrow

但 SQL Server 会使用此代码不停地运行

如何转换该查询?

【问题讨论】:

  • 创建一个 UFD 并使用该 UDF。有很多个重复的问题展示了如何做到这一点。更快更简洁的选择是使用 SQLCLR UDF 而不是 XML PATH 方法
  • @PanagiotisKanavos 什么是 UFD? (唯一分解域)???
  • @bsflasher 在数据库上下文中:User Defined Function.

标签: sql sql-server


【解决方案1】:

CROSS APPLY 的工作方式有点像INNER JOIN 的嵌套版本。

虽然OUTER APPLY 类似于LEFT JOIN 的嵌套版本。

所以试试这个例子:

create table filesanad
(
 id int identity(1,1) primary key,
 [row] int
);

insert into filesanad values 
(1),(1),(2),(2),(3)
GO
5 行受影响
create table tarafhesab
(
 id int identity(1,1) primary key,
 filesanadrow int,
 tarafhesabsharh varchar(30)
);

insert into tarafhesab 
(filesanadrow, tarafhesabsharh) values
(1,'foo'),(1,'bar'),
(2,'buz');
GO
3 行受影响
--
-- CROSS APPLY on a FOR XML
-- 
SELECT f.filesanadrow, ca.tarafhesabha
FROM
(
    SELECT [row] AS filesanadrow
    FROM filesanad
    GROUP BY [row]
) f
CROSS APPLY
(
    SELECT STUFF(q.x.value('.', 'NVARCHAR(MAX)'), 1, 1, '') AS tarafhesabha
    FROM
    (
        SELECT DISTINCT '; ' + t.tarafhesabsharh 
        FROM tarafhesab AS t
        WHERE t.filesanadrow = f.filesanadrow
        FOR XML PATH(''), type
    ) q(x)
    WHERE q.x IS NOT NULL
) ca;
GO
文件搜索 |塔拉菲萨巴 ------------: | :----------- 1 |酒吧;富 2 |嗡嗡声
--
-- OUTER APPLY on a FOR XML
-- 
SELECT f.filesanadrow, ca.tarafhesabha
FROM
(
    SELECT [row] AS filesanadrow
    FROM filesanad
    GROUP BY [row]
) f
OUTER APPLY
(
    SELECT STUFF(q.x.value('.', 'NVARCHAR(MAX)'), 1, 1, '') AS tarafhesabha
    FROM
    (
        SELECT DISTINCT '; ' + t.tarafhesabsharh 
        FROM tarafhesab AS t
        WHERE t.filesanadrow = f.filesanadrow
        FOR XML PATH(''), type
    ) q(x)
    WHERE q.x IS NOT NULL
) ca;
GO
文件搜索 |塔拉菲萨巴 ------------: | :----------- 1 |酒吧;富 2 |嗡嗡声 3 |
--
-- nested query with a FOR XML
-- 
SELECT 
f.[row] AS filesanadrow, 
(
    SELECT STUFF(q.x.value('.', 'NVARCHAR(MAX)'), 1, 1, '') AS tarafhesabha
    FROM
    (
        SELECT DISTINCT '; ' + t.tarafhesabsharh 
        FROM tarafhesab AS t
        WHERE t.filesanadrow = f.[row]
        FOR XML PATH(''), type
    ) q(x)
    WHERE q.x IS NOT NULL
) AS tarafhesabha
FROM filesanad f
GROUP BY f.[row]
GO
文件搜索 |塔拉菲萨巴 ------------: | :----------- 1 |酒吧;富 2 |嗡嗡声 3 |

db小提琴here

【讨论】:

  • 在 SQL Server 中可以,谢谢。但不幸的是,我无法在 Visual Studio 数据集设计器中交叉应用,因为它说:不支持 OUTER APPLY SQL 构造或语句
  • @bsflasher 哦,我不知道那个“数据集设计器”。它是否支持嵌套查询?例如select 'x' x, (select 'y') y;。因为OUTER APPLYCROSS APPLY 基本上做了类似于嵌套查询的事情。然后尝试将APPLY 中使用的查询放入嵌套查询中。
猜你喜欢
  • 2017-12-10
  • 2021-12-30
  • 2021-05-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-01-17
相关资源
最近更新 更多