seleccione puntuación máxima agrupados por fecha, mostrar fecha y hora completa
-
12-09-2019 - |
Pregunta
Gday, tengo una tabla que muestra una serie de resultados y datetimes se produjeron esos resultados. Me gustaría seleccionar el máximo de estas puntuaciones de cada día, sino mostrar la fecha y hora en que se produjo la partitura.
Estoy utilizando una base de datos Oracle (10g) y la mesa está estructurado de esta manera:
scoredatetime score (integer) --------------------------------------- 01-jan-09 00:10:00 10 01-jan-09 01:00:00 11 01-jan-09 04:00:01 9 ...
Me gustaría ser capaz de presentar los resultados de tales lo anterior se convierte en:
01-jan-09 01:00:00 11
Esta consulta siguiente me pone a mitad de camino .. pero no todo el camino.
select
trunc(t.scoredatetime), max(t.score)
from
mytable t
group by
trunc(t.scoredatetime)
No puedo unir el marcador sólo porque la misma puntuación alta puede haber sido alcanzado varias veces durante el día.
Le agradezco su ayuda!
Simon Edwards
Solución
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
En el caso de múltiples puntuaciones más altas dentro de un día, esto devuelve la fila correspondiente a la que se produjo la última en el día. Si quieres ver todas las calificaciones más altas en un día, eliminar scoredatetime la descripción de la orden por la especificación en la ventana row_number.
Como alternativa, puede hacer esto (aparecerá una lista de vínculos de puntuación más alta para una fecha):
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
Otros consejos
En primer lugar, aún no se ha especificado lo que debería suceder si dos o más filas dentro del mismo día contienen una alta puntuación igual.
Dos posibles respuestas a esta pregunta:
1) Sólo tienes que seleccionar una de las scoredatetime de, no importa cuál
En este caso no utilice auto une o análisis como se ve en las otras respuestas, porque hay una función de agregado especial que puede hacer su trabajo más eficiente. Un ejemplo:
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) Seleccionar todos los registros con la máxima puntuación.
En este caso es necesario análisis con un rango o función DENSE_RANK. Un ejemplo:
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.
Saludos, Rob.
Es posible que tenga dos instrucciones SELECT para sacar esto adelante: la primera para recoger la fecha y la puntuación máxima truncada asociado, y el segundo para tirar en los valores de fecha y hora actuales relacionados con la puntuación
.Probar:
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
Esto hará que en mejores lazos de puntuación también.
Para obtener una versión que selecciona sólo el alto puntaje más recientemente publicado para cada día:
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
Esto puede producir múltiples registros por fecha, si dos resultados diferentes fueron publicadas exactamente al mismo tiempo.