sql-server - 为什么 T-SQL CROSS APPLY 有时表现得像 LEFT JOIN
问题描述
我读过的大多数文档都表明 CROSS APPLY 的行为方式与 INNER JOIN 类似,只有在两个源表中都有匹配的行时,才会在输出中包含一行。
但是,情况似乎并非总是如此,例如,如果您运行以下 SQL 查询,结果将包含 3 行,其中一个包含许多 NULL,因为右侧表中没有行:
CREATE TABLE #Order
(
Id int PRIMARY KEY
)
CREATE TABLE #OrderItem
(
OrderId int NOT NULL,
Price decimal(18, 2) NOT NULL
)
INSERT INTO #Order
VALUES(1), (2), (3)
INSERT INTO #OrderItem
VALUES(1, 10), (1, 20), (3,100)
SELECT *
FROM #Order o
CROSS APPLY
(
SELECT SUM(Price) AS TotalPrice, COUNT(*) AS Items, MIN(Price) AS MinPrice
FROM #OrderItem
WHERE OrderId = o.Id
) t
DROP TABLE #Order
DROP TABLE #OrderItem
有谁知道这是为什么?
解决方案
TL;博士;
发生这种情况的原因是聚合是一个标量聚合。
有两种类型的聚合:
矢量聚合
需要一个
GROUP BY
子句如果输入没有行,则根本不返回任何行
标量聚合
无
GROUP BY
条款即使没有输入行,也始终返回至少一行。
COUNT
退货0
,别人退货NULL
。
您使用的是标量聚合,因此总是返回一行。
要获得矢量聚合,您需要添加一个GROUP BY
SELECT *
FROM #Order o
CROSS APPLY
(
SELECT SUM(oi.Price) AS TotalPrice, COUNT(*) AS Items, MIN(oi.Price) AS MinPrice
FROM #OrderItem oi
WHERE oi.OrderId = o.Id -- always specify inner table in column references
GROUP BY () -- the empty set
-- alternatively
GROUP BY oi.OrderId
) t
另请参阅@PaulWhite 的这篇优秀文章:标量和向量聚合的乐趣
推荐阅读
- python - 查找特定元数据的 xpath
- pdf - 在多页 PDF 中逐页阅读 PDF
- tidy - 错误:nlsModel 类的对象没有整洁的方法
- node.js - 在有效模式的情况下快速验证给出 404
- tensorflow - 带有图像的 pbtxt/pb 文件的推理测试
- java - 如何将地图定义为常量对象,而不是每次调用时都会创建的方法
- c++ - 如何在 C++ 上的游戏中添加加载游戏功能
- java - 如何从命令提示符运行驻留在另一个 jar 中的 jar
- php - 提供的 paytm 校验和无效
- java - 读取 Excel 表,将列数据存储在数组中,遍历数组中的每个值并将其与门户网站上的数据进行比较