SQL:使用 Sub Query 查询大于多个 Vendor 最大付款的记录
结论
把子查询中的 VendorID = 34 改为 VendorID IN (34, 35, 83),再通过 MAX() 取出这三个 Vendor 的最高付款金额:
SELECT VendorID, PaymentTotal
FROM Invoices
WHERE PaymentTotal > (
SELECT MAX(PaymentTotal)
FROM Invoices
WHERE VendorID IN (34, 35, 83)
);
查询会返回 PaymentTotal 严格大于 VendorID 34、35、83 所有付款记录中最高金额的记录,同时显示对应的 VendorID 和 PaymentTotal。
原因
原查询的子查询只有一个筛选条件:
WHERE VendorID = 34
所以外层查询仅以 VendorID 34 的付款记录作为比较对象,没有计算 VendorID 35 和 83 的数据。
使用 IN 可以一次筛选多个 Vendor:
WHERE VendorID IN (34, 35, 83)
MAX(PaymentTotal) 随后从这些 Vendor 的所有付款记录中取出最大值,外层查询再逐条判断付款金额是否高于这个值。
使用 ALL 的写法
如果题目明确要求使用 ALL,可以保留原有结构:
SELECT VendorID, PaymentTotal
FROM Invoices
WHERE PaymentTotal > ALL (
SELECT PaymentTotal
FROM Invoices
WHERE VendorID IN (34, 35, 83)
);
当子查询返回的付款金额均不为 NULL 时:
PaymentTotal > ALL (子查询结果)
表示 PaymentTotal 必须大于子查询返回的每一个值,效果等同于大于其中的最大值。
相比之下,MAX() 的写法更直观:先求出最高付款金额,再进行一次标量比较。
是否排除 34、35 和 83
上述查询会检查 Invoices 表中的所有记录。VendorID 34、35、83 的付款通常不可能高于其所在集合的最大值,但如果业务规则要求明确排除这三个 Vendor,可以在外层查询中增加条件:
SELECT VendorID, PaymentTotal
FROM Invoices
WHERE VendorID NOT IN (34, 35, 83)
AND PaymentTotal > (
SELECT MAX(PaymentTotal)
FROM Invoices
WHERE VendorID IN (34, 35, 83)
);
注意事项
如果 PaymentTotal 允许为 NULL,建议优先使用 MAX()。聚合函数 MAX() 会忽略 NULL,而 > ALL 的子查询只要包含 NULL,SQL 的三值逻辑就可能使比较结果变为未知,导致查询无法返回预期记录。
如果表中完全没有 VendorID 34、35、83 的付款记录,MAX() 会返回 NULL。此时:
PaymentTotal > NULL
不会匹配任何记录。如果业务上需要为“没有基准付款”的情况设置默认值,可以根据数据库类型使用 COALESCE,例如:
SELECT VendorID, PaymentTotal
FROM Invoices
WHERE PaymentTotal > COALESCE(
(
SELECT MAX(PaymentTotal)
FROM Invoices
WHERE VendorID IN (34, 35, 83)
),
0
);
这里使用 0 有两个前提:付款金额不会为负,并且业务上可以把“没有付款记录”视为最大值为 0。否则,应按照实际业务规则设置处理方式。
备注:内容仅供参考。
