假设下表:
ID Name Revision
--- ----- --------
1 blah 0
2 yada 1
3 blah 1
4 yada 0
5 blah 2
6 blah 3
如何获得两个记录,一个用于“blah”,另一个用于“yada”,最高版本号(3个用于blah,1个用于yada)?类似的东西:
ID Name Revision
--- ----- --------
6 blah 3
2 yada 1
此外,一旦检索到这些记录,如何按名称和修订排序?
我正在尝试创建一个主 - 详细信息视图,其中主记录是最新版本,详细信息包括以前的修订版。
答案 0 :(得分:5)
基本上,使用汇总功能MAX()
:
SELECT "Name", MAX("Revision") AS max_revison
FROM tbl
WHERE "Name" IN ('blah', 'yada');
GROUP BY "Name"
ORDER BY "Name"; -- ordering by revision would be pointless;
如果您需要从行中更多列,有几种方法。一种方法是将上面的子查询连接回基表:
SELECT t.*
FROM (
SELECT "Name", max("Revision") AS max_revison
FROM tbl
WHERE "Name" IN ('blah', 'yada');
GROUP BY "Name"
) AS sub
JOIN tbl AS t ON t."Revision" = sub.max_revison
AND t."Name" = sub."Name"
ORDER BY "Name";
通常,如果“修订版”不是唯一的(每个“名称”),则有可能每"Name"
个多行。您必须定义如何从共享相同最大“修订版”的一组对等方中挑选one
- 一个决胜局。
另一种方法是 NOT EXISTS
,不包括具有更多同行的行,可能更快:
SELECT t.*
FROM tbl AS t
WHERE "Name" IN ('blah', 'yada')
AND NOT EXISTS (
SELECT 1
FROM tbl AS t1
WHERE t1."Name" = t."Name"
AND t1."Revision" > t."Revision"
)
ORDER BY "Name";
或者您可以将 CTE 与分析函数(窗口函数)一起使用:
WITH cte AS (
SELECT *, ROW_NUMBER() OVER(PARTITION BY "Name" ORDER BY "Revision" DESC) AS rn
FROM tbl
WHERE "Name" IN ('blah', 'yada')
)
SELECT *
FROM cte
WHERE rn = 1;
最后一个略有不同:保证每"Name"
一行。如果您不使用更多ORDER BY
项,则在绑定时将选择任意行。如果您希望所有同行改为使用RANK()
。
答案 1 :(得分:2)
此方法将为每个Name选择具有该Name的最大修订号的行。结果将是您在帖子中寻找的确切输出。
SELECT *
FROM tbl a
WHERE a.revision = (select max(revision) from tbl where name = a.name)
ORDER BY a.name
答案 2 :(得分:1)