sql - 在两个表中返回一段时间的最大值

时间:2011-06-02 23:11:28

标签: sql join max

以下是我的问题的简化版本:

我有两张桌子:

学生

ST_STUDENT_ID  NAME   ST_DATE_TAKEN
-------------  -----  -------------
1              Jim    2011-01-01
2              Fred   2011-01-02
3              Sarah  2011-01-03
4              Nancy  2001-02-04

SCORES

SC_STUDENT_ID  SC_SCORE
-------------  --------
1              97
2              97
3              95
4              97

我需要将学生的分数提高一个月(比如一月份)。但是,我只想要一个学生,即使多个学生都收到了这个分数,并且该分数也可能存在于我的焦点月之外,所以这使我的查询变得复杂。我想要做的唯一方法是在每个嵌套的子查询中重做我的所有条件。有没有更好的办法。这里并不太可怕,但在我的实际问题中,标准更加复杂并且在许多表格中加入,重复它是一种痛苦,而且成本变得非常大。

SELECT ST_STUDENT_ID, ST_TIMESTAMP, SC_SCORE
FROM STUDENTS 
JOIN SCORES
  ON ST_STUDENT_ID = SC_STUDENT_ID
WHERE ST_STUDENT_ID = (
  SELECT MAX(ST_STUDENT_ID)
  FROM STUDENTS
  JOIN SCORES
    ON ST_STUDENT_ID = SC_STUDENT_ID
  WHERE ST_TIMESTAMP > '2011-01-01'
    AND ST_TIMESTAMP < '2011-02-01'
    AND SC_SCORE IS NOT NULL
    AND SC_SCORE = (
      SELECT MAX(SC_SCORE)
        FROM STUDENTS
      JOIN SCORES
        ON ST_STUDENT_ID = SC_STUDENT_ID
      WHERE ST_TIMESTAMP > '2011-01-01'
        AND ST_TIMESTAMP < '2011-02-01'))

2 个答案:

答案 0 :(得分:1)

如果您只需要一个分数,并且您的时间段将明确传递到查询中,那么这样的事情呢?

SELECT TOP 1 ST_STUDENT_ID, ST_TIMESTAMP, SC_SCORE
FROM STUDENTS 
JOIN SCORES ON ST_STUDENT_ID = SC_STUDENT_ID
WHERE ST_TIMESTAMP >= '2011-01-01'
AND ST_TIMESTAMP <= '2011-02-01'
ORDER BY SC_SCORE DESC, ST_STUDENT_ID DESC

该语法适用于MS SQL Server - 不同的RDBMS对“TOP 1”概念的语法略有不同。

[我在后面的评论中看到你正在使用DB2 - 在这种情况下,语法显然是FETCH FIRST 1 ROWS ONLY。]

请注意,我正在遵循您示例中的逻辑,这意味着具有最高ID的学生优先。上课迟到的良好动机; - )

答案 1 :(得分:1)

(假设SQL Server 2005或更高版本,或支持CTE和窗口函数的其他RDMBS)

类似的东西:

;With OrderedScores as (
SELECT
    ST_STUDENT_ID,
    ST_TIMESTAMP,
    SC_SCORE,
    ROW_NUMBER() OVER (ORDER BY SC_SCORE desc,newid()) as rn /* Ordered randomly within same score */
FROM
    STUDENTS
        join
    SCORES
        on ST_STUDENT_ID = SC_STUDENT_ID
WHERE
    ST_TIMESTAMP >= '20110101' and
    ST_TIMESTAMP < '20110201'
)
select * from OrderedScores where rn = 1

显然,您可以使用窗口函数的ORDER BY内的条件来确定当存在关系时选择哪个学生(在上面它是随机的;再次假设SQL Server - 如果是另一个RDBMS,{{ 1}}应替换为其他东西)

此外,我认为我的日期条件正确无误 - 在原始查询中,您有一组使用newid()>的标准(因此不包括Jim),以及另一方面,你使用<<=,其中可能包括2月1日测试过的学生。