我正在尝试查询最近一个学期的会议列表,其中学期由两个字段(年,学期)决定。这是架构的基本概要:
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,Semester = 2,这是不正确的。我尝试了几种使用嵌套子查询和内部联接的方法,但是无法完成某些工作。解决这个问题最简单的方法是什么?
答案 0 :(得分:2)
使用窗口功能:
SELECT Year, Semester, RANK() OVER(ORDER BY Year DESC, Semester DESC) R
FROM your_table;
R
将是一个包含" rank"的列。这对夫妇(年,学期)。然后,您可以将此列用作过滤器,例如:
WITH TT AS (
SELECT Year, Semester, RANK() OVER(ORDER BY Year DESC, Semester DESC) R
FROM your_table
)
SELECT ...
FROM TT
WHERE R = 1;
如果您不希望排名之间存在差距,则可以使用dense_rank
代替rank
。
这个答案假设您使用的RDBMS足够先进,可以提供窗口功能(即不是MySQL)
答案 1 :(得分:1)
如果有更有效的方法(并避免重复的子查询),我不会感到惊讶,但这会得到你想要的答案:
SELECT * FROM table WHERE Year =
(SELECT MAX(Year) FROM table)
AND Semester =
(SELECT MAX(Semester) FROM table WHERE Year =
(SELECT MAX(Year) FROM table))
答案 2 :(得分:1)
这是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
)
答案 3 :(得分:1)
我一直在思考这个问题,有一个更简单的方法来解决这个问题:
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
请注意,这种变体应该适用于所有 dbs(支持子查询中的限制子句的任何内容);这是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
(......和working fiddle)
鉴于一些数据in this answer,这对Oracle应该是高性能的,我也怀疑其他dbs(考虑到优化器允许的快捷方式)。在没有提供分区子句的大多数情况下(无窗口),这应该能够替换ROW_NUMBER()
之类的东西。
答案 4 :(得分:0)
为什么不简单地使用ORDER BY
???
SELECT * FROM table
Where Year = (Select Max(Year) from table) /* optional clause to select only 2014*/
Order by Semester ASC, Year DESC, Otherfields; /*numericaly lowest sem first. in case of sem clash, sort by descending year first */
修改强>
如果您需要2014年的有限结果,请使用Limit
子句( for mysql )
SELECT * FROM table
Where Year = (Select Max(Year) from table)
Order by Semester ASC, Year DESC, Otherfields
LIMIT 10;
首先order
,然后获得限制 - 10,所以你得到有限的结果集!
这将获取如下输出:
Otherfields Year Semester
meeting1 2014 1
meeting2 2014 1
meeting1 2013 1
meeting2 2013 2
答案 5 :(得分:0)
在这里回答我自己的问题:
此查询是在存储过程中运行的,因此我继续在查询的其余部分之前在单独的查询中找到最大年份/学期。这很可能是效率低下且不优雅的,但它也是最容易理解的方法 - 我不需要担心我的团队中的其他成员会对此感到困惑。我会在这里留下这个问题,因为它通常适用于许多其他情况,似乎有一些很好的答案提供替代方法。
-- 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;