HAVING - GROUP BY获取最新记录

时间:2013-06-29 12:58:16

标签: sql sql-server oracle group-by greatest-n-per-group

我有一个名为RESULTS的表,如下所示:

RESULTS_IDN    NAME    SUBJECT    YEAR    QUALIFIED
1              MARK    ENGLISH    1989    N
3              MARK    ENGLISH    1991    N
5              MARK    ENGLISH    1993    Y
7              MARK    ENGLISH    1995    N
2              MARK    MATH       1990    N
5              MARK    MATH       1993    N
6              MARK    MATH       1995    Y
4              MARK    SCIENCE    1991    N
9              MARK    SCIENCE    1997    Y

我需要知道他编写的最新考试的SUBJECT的候选人资格状态,如何为此编写查询(ORACLE / MSSQL)?

例如输入

NAME,SUBJECT  OUTPUT NAME IDN SUBJECT YEAR Q
MARK,ENGLISH  OUTPUT MARK 7   ENGLISH 1995 N 
MARK SCIENCE  OUTPUT MARK 9   SCIENCE 1997 Y
MARK MATH     OUTPUT MARK 6   MATH    1995 Y

我知道解决这个问题的一种方法。

(SELECT NAME SUBJECT YEAR MAX(YEAR) YEAR
FROM RESULTS WHERE NAME = 'MARK' AND SUBJECT ='MATH'
GROUP BY NAME SUBJECT YEAR) LATEST 

将上面的表格加入IDN到同一个表格,我可以得到结果。但这是双重工作。无论如何我可以参加MAX(YEAR)并使用HAVING CLAUSE或其他东西获得相应的年份吗?我需要对GROUP BY数据进行2次操作,一次最新,以及相应的合格状态。

PS:当然,DB中有100名候选人的记录。

更新:根据答案,此问题也被归类为最大n组/ 问题2.有趣的是,知道这是DB中的分类问题。

2 个答案:

答案 0 :(得分:3)

在Oracle和SQL Server中,您可以使用分析/窗口函数RANK()或ROW_NUMBER()来实现此目的:

select *
  from ( select a.*
              , rank() over ( partition by name, subject order by year desc ) rnk
           from ... a
                )
 where rnk = 1

对于每namesubject最新的行,RANK()将返回1,ROW_NUMBER()将返回随机行。

仅在Oracle中,您可以使用KEEP为您提供相同的结果:

select name, subject, max(year) as year
     , max(qualified) keep (dense_rank first order by year desc) as qualified
  from ...
 group by name, subject

答案 1 :(得分:1)

这是一直在彻底改造的问题
SELECT t1.*
FROM RESULTS AS t1
LEFT JOIN RESULTS AS t2
  ON t1.NAME = t2.NAME AND t1.SUBJECT = t2.SUBJECT AND t1.YEAR < t2.YEAR
WHERE t2.NAME IS NULL