1

Gday,我有一个表格,显示了一系列分数和这些分数发生的日期时间。我想选择每天这些分数的最大值,但显示分数发生的日期时间。

我正在使用 Oracle 数据库(10g),表的结构如下:

    得分时间分数(整数)
    --------------------------------------
    09 年 1 月 1 日 00:10:00 10
    09 年 1 月 1 日 01:00:00 11
    09 年 1 月 1 日 04:00:01 9
    ...

我希望能够呈现上述结果:

09 年 1 月 1 日 01:00:00 11

下面的查询让我走到了一半……但不是一路。

select 
   trunc(t.scoredatetime), max(t.score)
from 
   mytable t
group by
   trunc(t.scoredatetime)

我不能仅凭分数加入,因为同一天可能已经多次获得相同的高分。

我感谢您的帮助!

西蒙·爱德华兹

4

3 回答 3

3
with mytableRanked(d,scoredatetime,score,rk) as (
  select
    scoredatetime,
    score,
    row_number() over (
      partition by trunc(scoredatetime)
      order by score desc, scoredatetime desc
    )
  from mytable
)
  select
    scoredatetime,
    score
  from mytableRanked    
  where rk = 1
  order by date desc

在一天内有多个高分的情况下,这将返回与当天最晚出现的那个对应的行。如果您想查看一天中的所有最高分数,请从 row_number 窗口中的 order by specification 中删除 scoredatetime desc。

或者,您可以这样做(它会列出某个日期的高分关系):

select
  scoredatetime,
  score
from mytable
where not exists (
  select *
  from mytable as M2
  where trunc(M2.scoredatetime) = trunc(mytable.scoredatetime)
  and M2.score > mytable.scoredatetime
)
order by scoredatetime desc
于 2009-09-21T04:12:14.577 回答
1

首先,您还没有指定如果同一天内的两行或多行包含相同的高分会发生什么。

这个问题有两个可能的答案:

1) 只选择其中一个得分时间,不管是哪一个

在这种情况下,不要像在其他答案中看到的那样使用自联接或分析,因为有一个特殊的聚合函数可以更有效地完成您的工作。一个例子:

SQL> create table mytable (scoredatetime,score)
  2  as
  3  select to_date('01-jan-2009 00:10:00','dd-mon-yyyy hh24:mi:ss'), 10 from dual union all
  4  select to_date('01-jan-2009 01:00:00','dd-mon-yyyy hh24:mi:ss'), 11 from dual union all
  5  select to_date('01-jan-2009 04:00:00','dd-mon-yyyy hh24:mi:ss'), 9 from dual union all
  6  select to_date('02-jan-2009 00:10:00','dd-mon-yyyy hh24:mi:ss'), 1 from dual union all
  7  select to_date('02-jan-2009 01:00:00','dd-mon-yyyy hh24:mi:ss'), 1 from dual union all
  8  select to_date('02-jan-2009 04:00:00','dd-mon-yyyy hh24:mi:ss'), 0 from dual
  9  /

Table created.

SQL> select max(scoredatetime) keep (dense_rank last order by score) scoredatetime
  2       , max(score)
  3    from mytable
  4   group by trunc(scoredatetime,'dd')
  5  /

SCOREDATETIME       MAX(SCORE)
------------------- ----------
01-01-2009 01:00:00         11
02-01-2009 01:00:00          1

2 rows selected.

2) 选择所有得分最高的记录。

在这种情况下,您需要使用 RANK 或 DENSE_RANK 函数进行分析。一个例子:

SQL> select scoredatetime
  2       , score
  3    from ( select scoredatetime
  4                , score
  5                , rank() over (partition by trunc(scoredatetime,'dd') order by score desc) rnk
  6             from mytable
  7         )
  8   where rnk = 1
  9  /

SCOREDATETIME            SCORE
------------------- ----------
01-01-2009 01:00:00         11
02-01-2009 00:10:00          1
02-01-2009 01:00:00          1

3 rows selected.

问候,罗布。

于 2009-09-21T07:26:42.847 回答
0

您可能需要两个 SELECT 语句来完成此操作:第一个用于收集截断的日期和关联的最大分数,第二个用于提取与分数关联的实际日期时间值。

尝试:

SELECT T.ScoreDateTime, T.Score
FROM
(
 SELECT
    TRUNC(T.ScoreDateTime) ScoreDate, MAX(T.score) BestScore
 FROM 
    MyTable T
 GROUP BY 
    TRUNC(T.ScoreDateTime)
) ByDate
INNER JOIN MyTable T 
    ON TRUNC(T.ScoreDateTime) = ByDate.ScoreDate and T.Score = ByDate.BestScore
ORDER BY T.ScoreDateTime DESC

这也将拉入最佳得分关系。

对于仅选择每天最近发布的高分的版本:

SELECT T.ScoreDateTime, T.Score
FROM
(
 SELECT
    TRUNC(T.ScoreDateTime) ScoreDate, 
    MAX(T.score) BestScore, 
    MAX(T.ScoreDateTime) BestScoreTime
 FROM 
    MyTable T
 GROUP BY 
    TRUNC(T.ScoreDateTime)
) ByDate
INNER JOIN MyTable T 
    ON T.ScoreDateTime = ByDate.BestScoreTime and T.Score = ByDate.BestScore
ORDER BY T.ScoreDateTime DESC

如果两个不同的分数同时发布,这可能会在每个日期产生多个记录。

于 2009-09-21T04:05:39.163 回答