将相关子查询重写为 CROSS APPLY

Posted

技术标签:

【中文标题】将相关子查询重写为 CROSS APPLY【英文标题】:Rewrite correlated subquery to CROSS APPLY 【发布时间】:2021-03-15 13:39:57 【问题描述】:

所以我尝试使用CROSS APPLY,但似乎无法正确使用。

我有一些类似这样的查询:

SELECT COL1, COL2
FROM dbo.tableA AS A
WHERE COL3 = (SELECT MAX(COL4)
              FROM dbo.tableA AS B
              WHERE A.COL1 = B.COL1) AS SUB

我试试这个:

SELECT COL1, COL2
FROM dbo.tableA AS A
CROSS APPLY (SELECT MAX(COL4) AS MAX_DATE
              FROM TABLEA AS B
              WHERE A.COL1 = B.COL1) AS SUB 

但是当我使用CROSS APPLY 时,我总是返回更多行。我的错在哪里?

【问题讨论】:

【参考方案1】:

如果您希望这两个查询同样工作,您在第二个查询中缺少 WHERE

SELECT COL1, COL2
FROM dbo.tableA AS A
CROSS APPLY (SELECT MAX(COL4) AS MAX_DATE
              FROM TABLEA AS B
              WHERE A.COL1 = B.COL1) AS SUB 
WHERE A.COL3 = SUB.MAX_DATE;

【讨论】:

谢谢,当然 :-)。将子查询放在表值函数中是否有助于提高性能。我在桌子上有一个 POC 索引。还是该函数只会帮助使代码更具可读性? PS它说我必须等待才能接受。 老实说,这不太可能有所不同,但您可以通过测试轻松找到。 我仍然看到 CROSS APPLY 版本的行数更多。你能解释一下吗? 不,@xhr489,我没有样本数据或预期结果。上面的应该是一样的,所以我怀疑这里没有别的了。 可能不会有任何区别,但是您需要 set statistics time on 并比较 逻辑读取 选择最少的,或者如果相同无关紧要。 【参考方案2】:

除了APPLY 重写,因为这是一个自连接,它也可以通过MAX 窗口聚合来完成:

SELECT COL1, COL2
FROM (
    SELECT *,
        MAX(COL4) OVER (PARTITION BY COL1) AS mx
    FROM dbo.tableA
) AS A
WHERE COL3 = mx

【讨论】:

谢谢,你能问一下为什么两个版本的结果略有不同吗? 没有样本数据,没有。您发布的查询是否完整 没有外部查询在 where 子句中有额外的谓词 我找到了原因,我错过了一些东西 :-)

以上是关于将相关子查询重写为 CROSS APPLY的主要内容,如果未能解决你的问题,请参考以下文章

Hive 上的 CROSS APPLY SQL Server 查询

CROSS APPLY 风格与性能

使用 CROSS APPLY 与 OUTER APPLY 连接查询

使用 CROSS APPLY 与 OUTER APPLY 连接查询

使用 CROSS APPLY 与 OUTER APPLY 连接查询

使用 CROSS APPLY 与 OUTER APPLY 连接查询