我有一个包含id(加上其他一些列)的“main”表和一个通过[main id]列连接到main.id的aka表。以下查询返回main中的一些列以及来自aka的串联逗号分隔的“lastName”列:
SELECT m.id, m.name,
(SELECT a.[lastname] + ',' AS [text()]
FROM aka a
WHERE a.[main id] = m.[id]
FOR xml path ('')) [akas]
FROM main m
这很好用,但我想知道是否有办法避免在子查询中这样做?
答案 0 :(得分:2)
使用CROSS APPLY
,您可以从SELECT
列表中移动子查询:
SELECT m.id, m.name,
(SELECT a.[lastname] + ',' AS [text()]
FROM aka a
WHERE a.[main id] = m.[id]
FOR xml path ('')) [akas]
FROM main m;
为:
SELECT m.id, m.name, s.akas
FROM main m
CROSS APPLY (SELECT a.[lastname] + ',' AS [text()]
FROM aka a
WHERE a.[main id] = m.[id]
FOR xml path ('')) AS s(akas)
注意:
WHERE s.akas ...
SELECT
列表中的长子查询可能不太可读OUTER APPLY
。答案 1 :(得分:1)
一般来说,技术视图中的子查询没有任何内容......
由于可读性或多重参考,您可能更喜欢APPLY
。
每当您将子查询直接放入列的列表中时,如下所示:
SELECT Column1
,Column2
,(SELECT x FROM y) AS Column3
,[...]
...此子选择必须提供
使用FOR XML PATH(''),TYPE
可以使结果为XML类型的单个值。这使得可以返回许多行/列"作为一个"。没有,TYPE
,它将是XML"作为文本"。 XML的串联技巧是可能的,因为生成具有空标签名称的XML并返回"作为文本"。但无论如何:返回的值只是一点信息,因此适合列列表。
每当您期望多行时,您必须强制将其作为一位数据(例如 - 常见! - SELECT TOP 1 x FROM y ORDER BY SomeSortKey
,它会带回第一个或最后一个或... 。)
获得1:n数据需求的所有其他意图'加入'或者'申请'。对于标量数据,如您的情况,实际上没有区别,无论您使用子选择还是APPLY
。
答案 2 :(得分:0)
由于您为最终字符串组合了任意数量的记录,因此您拥有的是在SQL中执行此操作的最佳选项。通常,您需要为每个项目返回一行,如果您想要CSV字符串,则在您的客户端代码中构建它。