2009-09-21 2 views
1

Gday, у меня есть таблица, которая показывает серию оценок и времени, когда эти баллы имели место. Я бы хотел выбрать максимум этих баллов за каждый день, но отобразить дату и время, в которые произошла оценка.выберите максимальный балл, сгруппированный по дате, отобразите полное datetime

Я использую базу данных Oracle (10g) и таблицу структурирована следующим образом:

 scoredatetime    score (integer) 
    --------------------------------------- 
    01-jan-09 00:10:00  10 
    01-jan-09 01:00:00  11 
    01-jan-09 04:00:01  9 
    ...

Я хотел бы иметь возможность представить результаты таких выше становится:

 01-jan-09 01:00:00  11

Этот следующий запрос достает меня на полпути, но не полностью.

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

Я не могу присоединиться к игре только потому, что один и тот же высокий балл мог быть достигнут несколько раз в течение дня.

Я ценю вашу помощь!

Саймон Эдвардс

ответ

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 

В случае нескольких высоких баллов за один день это возвращает строку, соответствующую последней, произошедшей за день. Если вы хотите увидеть все самые высокие баллы за день, удалите биттутез desc из заказа по спецификации в окне row_number.

В качестве альтернативы, вы можете сделать это (это будет список связей высокого балла по дате):

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 
0

Вам может понадобиться два ЗЕЬЕСТА, чтобы провернуть это: первый сбор усеченной даты и связанный максимальный балл, а второй тянуть в фактических значениях даты и времени, связанные со счетом.

Try:

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 

Это может производить несколько записей в дату, если две разные оценки были размещены в точно то же самое время.

+0

Спасибо, Дэвид! Я подозреваю, что все будет намного более жарким, если я хочу получить один балл в день (и взять любой из самых высоких баллов за этот день в качестве номинального «max»). Я воспользуюсь решением, которое вы предоставили. Приветствия. –

+0

@Simon: Это не было бы грязнее, вам нужно было бы захватить MAX (T.ScoreDateTime) во внутреннем запросе и использовать это поле как часть вашего условия JOIN. Рад, что это сработало для вас! –

1

Прежде всего, вы еще не указать, что должно произойти, если два или более строк в пределах одного день содержат равный высокий балл.

Два возможных варианта ответа на этот вопрос:

1) Просто выберите один из scoredatetime, это не имеет значения, один

В этом случае не использовать сам присоединяется или аналитика, как вы видите другие ответы, потому что есть специальная функция агрегата, которая может сделать вашу работу более эффективной.Пример:

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. 

С уважением, Роб.

Смежные вопросы