Sql 查找多列上的最大值
我试图查询最近一学期的会议列表,其中学期由两个字段(年份、学期)确定。下面是该模式的基本概要:Sql 查找多列上的最大值,sql,oracle11g,Sql,Oracle11g,我试图查询最近一学期的会议列表,其中学期由两个字段(年份、学期)确定。下面是该模式的基本概要: Otherfields Year Semester meeting1 2014 1 meeting2 2014 1 meeting3 2013 2 ... etc ... 由于应先考虑本年度的最大值,然后再考虑本学期的最大值,因此我的结果应如下所示: Otherfields Year Semester meeting1
Otherfields Year Semester
meeting1 2014 1
meeting2 2014 1
meeting3 2013 2
... etc ...
由于应先考虑本年度的最大值,然后再考虑本学期的最大值,因此我的结果应如下所示:
Otherfields Year Semester
meeting1 2014 1
meeting2 2014 1
不幸的是,在每一列上单独使用MAX()函数将试图找到Year=2014,term=2,这是不正确的。我尝试了两种使用嵌套子查询和内部联接的方法,但都没有成功。解决这个问题最直接的方法是什么?如果有更有效的方法来解决这个问题(并避免重复的子查询),我不会感到惊讶,但这将得到您想要的答案:
SELECT * FROM table WHERE Year =
(SELECT MAX(Year) FROM table)
AND Semester =
(SELECT MAX(Semester) FROM table WHERE Year =
(SELECT MAX(Year) FROM table))
您为什么不直接使用“订购依据” 这样,它会更容易处理,也不会那么凌乱!!:) 编辑 如果您需要2014年的有限结果,请使用
Limit
子句(对于mysql)
它将先下单
,然后得到限制-10,这样你就得到了你的有限结果集
这将获取如下输出:
Otherfields Year Semester
meeting1 2014 1
meeting2 2014 1
meeting1 2013 1
meeting2 2013 2
使用窗口功能:
SELECT Year, Semester, RANK() OVER(ORDER BY Year DESC, Semester DESC) R
FROM your_table;
R
将是一列,包含这对夫妇的“等级”(年份、学期)。然后可以将此列用作筛选器,例如:
WITH TT AS (
SELECT Year, Semester, RANK() OVER(ORDER BY Year DESC, Semester DESC) R
FROM your_table
)
SELECT ...
FROM TT
WHERE R = 1;
如果不希望列组之间存在间隙,可以使用densite\u-rank
而不是rank
这个答案假设您使用的RDBMS足够先进,可以提供窗口功能(即不是MySQL)这里是Postgres:
with table2 as /*virtual temporary table*/
(
select *, year::text || semester as yearsemester
from table
)
select Otherfields, year, semester
from table2
where (Otherfields, yearsemester) in
(
select Otherfields, max(yearsemester)
from table2
group by Otherfields
)
我想得太多了,有一个简单得多的方法:
SELECT Meeting.year, Meeting.semester, Meeting.otherFields
FROM Meeting
JOIN (SELECT year, semester
FROM Meeting
WHERE ROWNUM = 1
ORDER BY year DESC, semester DESC) MostRecent
ON MostRecent.year = Meeting.year
AND MostRecent.semester = Meeting.semester
(及)
注意,这种变体应该适用于几乎alldbs(在子查询中支持限制子句的任何内容);以下是MySQL版本,例如:
SELECT Meeting.year, Meeting.semester, Meeting.otherFields
FROM Meeting
JOIN (SELECT year, semester
FROM Meeting
ORDER BY year DESC, semester DESC
LIMIT 1) MostRecent
ON MostRecent.year = Meeting.year
AND MostRecent.semester = Meeting.semester
(……和)
考虑到一些数据,这对Oracle来说应该是有效的,我怀疑其他数据库也会如此(考虑到优化器可以采用的快捷方式)。在大多数没有提供分区子句(没有窗口)的情况下,这应该能够代替使用诸如
行号()之类的内容。在这里回答我自己的问题:
这个查询是在一个存储过程中运行的,所以我在查询的其余部分之前,在单独的查询中找到了最大年/学期数。这很可能是低效和不雅的,但也是最容易理解的方法——我不需要担心我的团队中的其他成员会被它弄糊涂。我将把这个问题留在这里,因为它通常适用于许多其他情况,而且似乎有一些很好的答案提供了替代方法
-- Find the most recent year.
SELECT MAX(year) INTO max_year FROM meeting;
-- Find the most recent semester in the year.
SELECT MAX(semester) INTO max_semester FROM meeting WHERE year = max_year;
-- Open a ref cursor for meetings in most recent year/semester.
OPEN meeting_list FOR
SELECT otherfields, year, semester
FROM meeting
WHERE year = max_year
AND semester = max_semester;
mysql
或oracle
??就个人而言,我会创建一个年/学期表,本质上类似于常规日历表(或者作为一个表中的字段)。然后你只需将年/学期id放在这个表中。这确实需要一个额外的查询连接(年/学期可能是连续的这一事实是一个不应该依赖的实现细节),但应该是一个快速的连接。此外,还可以很容易地给出学期开始/结束日期等。这并不能消除上学期会议以外的行。我不明白你的意思……你能重新措辞吗?你的查询将返回表中的所有行,而原始海报只需要上学期的行。耶,我同意,这就是我后来添加,where
子句的原因,另外,为了限制返回的行,OP可以使用limit
,但他/她没有提到DB正在使用什么!!嗯,不。首先,你这学期的顺序是错误的。如果有10个以上的会议,会发生什么情况?是的-您可以修改双嵌套的会议以用作子查询表引用,并将其作为联接包含。虽然Oracle有更好的操作可用,但这将在其他数据库(如MySQL)中工作。对于没有更好手段的数据库,组合相关字段是一个可行的选择,尽管我会以不同的方式构造查询的其余部分。我猜这是在Oracle中运行此查询最有效的方法。出于好奇,RANK()函数是Oracle特有的,还是可以在不同的DBMS之间移植?(例如MSSQL、PostgreSQL)在任何具有窗口函数的DBMS中都应该有一个等价物,但我使用PostgreSQL编写了这个特定的查询。
SELECT Meeting.year, Meeting.semester, Meeting.otherFields
FROM Meeting
JOIN (SELECT year, semester
FROM Meeting
ORDER BY year DESC, semester DESC
LIMIT 1) MostRecent
ON MostRecent.year = Meeting.year
AND MostRecent.semester = Meeting.semester
-- Find the most recent year.
SELECT MAX(year) INTO max_year FROM meeting;
-- Find the most recent semester in the year.
SELECT MAX(semester) INTO max_semester FROM meeting WHERE year = max_year;
-- Open a ref cursor for meetings in most recent year/semester.
OPEN meeting_list FOR
SELECT otherfields, year, semester
FROM meeting
WHERE year = max_year
AND semester = max_semester;