在旧版本的 Oracle 中,在提供分析函数之前,我们会使用如下查询返回指定的结果集:
SELECT f.group
, f.recipe
, f.priority
FROM foo f
JOIN ( SELECT g.group
, g.recipe
, MAX(g.priority) AS max_priority
FROM foo g
GROUP BY g.group, g.recipe
) m
ON m.group = f.group AND m.recipe = f.recipe
ORDER BY f.group
, m.max_priority DESC
, f.recipe
, f.priority DESC
这种方法适用于其他没有分析功能的数据库,例如 MySQL。
注意:上面的查询不是 NULL 安全的,因为 JOIN 谓词将消除组或配方列具有 NULL 值的行。它可以设为 NULL 安全的,但它会使 SQL 稍微复杂一些。
SELECT f.group
, f.recipe
, f.priority
FROM foo f
JOIN ( SELECT g.group
, g.recipe
, MAX(g.priority) AS max_priority
FROM foo g
GROUP BY g.group, g.recipe
) m
ON (m.group = f.group OR COALESCE(m.group,f.group) IS NULL)
AND (m.recipe = f.recipe OR COALESCE(m.recipe,f.recipe) IS NULL)
ORDER BY f.group
, m.max_priority DESC
, f.recipe
, f.priority DESC
使用 SELECT 列表中的相关子查询也可以获得等效结果,只是该结果集在结果集中包含一个额外的“max_priority”列。
SELECT f.group
, f.recipe
, f.priority
, (SELECT MAX(g.priority)
FROM foo g
WHERE (g.group = f.group OR COALESCE(g.group,f.group) IS NULL)
AND (g.recipe = f.recipe OR COALESCE(g.recipe,f.recipe) IS NULL)
) AS max_priority
FROM foo f
ORDER BY f.group
, 4 DESC
, f.recipe
, f.priority DESC
(我还没有测试是否可以从 SELECT 列表中删除相关的子查询并完全移至 ORDER BY 子句。如果可行,我们将消除返回额外的列,但该查询看起来非常非常奇怪。)另一个选项(省略该额外列)是将此查询(作为内联视图)包装在另一个查询中。
SELECT e.group
, e.recipe
, e.priority
FROM (
SELECT f.group
, f.recipe
, f.priority
, (SELECT MAX(g.priority)
FROM foo g
WHERE (g.group = f.group OR COALESCE(g.group,f.group) IS NULL)
AND (g.recipe = f.recipe OR COALESCE(g.recipe,f.recipe) IS NULL)
) AS max_priority
FROM foo f
) e
ORDER BY e.group
, e.max_priority DESC
, e.recipe
, e.priority DESC