在连接列时是否可以避免选择子查询?

时间:2016-04-30 20:05:59

标签: sql-server subquery

我有一个包含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 

这很好用,但我想知道是否有办法避免在子查询中这样做?

3 个答案:

答案 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)

注意:

  • 您可以多次参考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字符串,则在您的客户端代码中构建它。