Mi mesa es:
id home datetime player resource
---|-----|------------|--------|---------
1 | 10 | 04/03/2009 | john | 399
2 | 11 | 04/03/2009 | juliet | 244
5 | 12 | 04/03/2009 | borat | 555
3 | 10 | 03/03/2009 | john | 300
4 | 11 | 03/03/2009 | juliet | 200
6 | 12 | 03/03/2009 | borat | 500
7 | 13 | 24/12/2008 | borat | 600
8 | 13 | 01/01/2009 | borat | 700
Necesito seleccionar cada distinto home
tenga el valor máximo de datetime
.
El resultado sería:
id home datetime player resource
---|-----|------------|--------|---------
1 | 10 | 04/03/2009 | john | 399
2 | 11 | 04/03/2009 | juliet | 244
5 | 12 | 04/03/2009 | borat | 555
8 | 13 | 01/01/2009 | borat | 700
Yo he tratado:
-- 1 ..by the MySQL manual:
SELECT DISTINCT
home,
id,
datetime AS dt,
player,
resource
FROM topten t1
WHERE datetime = (SELECT
MAX(t2.datetime)
FROM topten t2
GROUP BY home)
GROUP BY datetime
ORDER BY datetime DESC
No funciona El conjunto de resultados tiene 130 filas, aunque la base de datos contiene 187. El resultado incluye algunos duplicados de home
.
-- 2 ..join
SELECT
s1.id,
s1.home,
s1.datetime,
s1.player,
s1.resource
FROM topten s1
JOIN (SELECT
id,
MAX(datetime) AS dt
FROM topten
GROUP BY id) AS s2
ON s1.id = s2.id
ORDER BY datetime
No Da todos los registros.
-- 3 ..something exotic:
Con varios resultados.
id
,player
yresource
de una fila no máxima para un hogar dado, es decir, para home = 10, puede obtener:3 | 10 | 04/03/2009 | john | 300
En otras palabras, no garantiza que todas las columnas de una fila en el conjunto de resultados pertenezcan a max (fecha y hora) para el hogar dado.La
MySQL
solución más rápida , sin consultas internas y sinGROUP BY
:Explicacion :
Únete a la tabla consigo mismo usando la
home
columna. El uso deLEFT JOIN
garantiza que todas las filas de la tablam
aparezcan en el conjunto de resultados. Aquellos que no tienen una coincidencia en la tablab
tendránNULL
s para las columnas deb
.La otra condición en el
JOIN
pide que coincida solo con las filasb
que tienen un valor mayor en ladatetime
columna que la fila dem
.Usando los datos publicados en la pregunta,
LEFT JOIN
producirá estos pares:Finalmente, la
WHERE
cláusula mantiene solo los pares que tienenNULL
s en las columnas deb
(están marcados con*
en la tabla anterior); Esto significa que, debido a la segunda condición de laJOIN
cláusula, la fila seleccionadam
tiene el mayor valor en la columnadatetime
.Lea el libro Antipatterns de SQL: Evitar las trampas de la programación de bases de datos para obtener otros consejos de SQL.
fuente
SQLite
, el primero es mucho más lento que la versión de La Voie cuando no hay índice en la columna coincidente (es decir, "hogar"). (Probado con 24k filas que resultan en 13k filas)home
ydatetime
, y eldatetime
es el máximo para ese particularhome
?ON
cláusula. Fe... ON ... AND m.id < b.id
para mantener la entrada más reciente (la que tiene la mayorid
) cuando dos filas tienen los mismos valores enhome
ydatetime
columnas y es el máximodatetime
.Aquí va la versión T-SQL :
EDITAR
Desafortunadamente, no hay función RANK () OVER en MySQL.
Pero se puede emular, consulte Funciones de Emulación Analítica (Clasificación AKA) con MySQL .
Entonces esta es la versión de MySQL :
fuente
Esto funcionará incluso si tiene dos o más filas para cada una
home
con igualDATETIME
's:fuente
WHERE ti.home = t1.home
- ¿Puedes explicar la sintaxis?select
consulta que tiene la líneaWHERE ti.home = t1.home
no necesita laFROM
cláusula que definet1
. Entonces, ¿cómo se usa?Creo que esto te dará el resultado deseado:
PERO si necesita otras columnas también, solo haga una unión con la tabla original (verifique la
Michael La Voie
respuesta)Atentamente.
fuente
Dado que las personas parecen seguir encontrándose con este hilo (la fecha del comentario varía de 1.5 años) no es esto mucho más simple:
SELECT * FROM (SELECT * FROM topten ORDER BY datetime DESC) tmp GROUP BY home
No se necesitan funciones de agregación ...
Salud.
fuente
También puede probar este y para tablas grandes el rendimiento de la consulta será mejor. Funciona cuando no hay más de dos registros para cada hogar y sus fechas son diferentes. Una mejor consulta general de MySQL es una de Michael La Voie anterior.
O en el caso de Postgres o aquellos dbs que proporcionan funciones analíticas intente
fuente
SQLite
, el primero es mucho más lento que la versión de La Voie cuando no hay índice en la columna coincidente (es decir, "inicio").Esto funciona en Oracle:
fuente
fuente
Pruebe esto para SQL Server:
fuente
fuente
Aquí está la versión de MySQL que imprime solo una entrada donde hay duplicados MAX (fecha y hora) en un grupo.
Puede probar aquí http://www.sqlfiddle.com/#!2/0a4ae/1
Data de muestra
Versión MySQL con variable de usuario
Outout de respuestas aceptadas
fuente
Otra forma de obtener la fila más reciente por grupo usando una subconsulta que básicamente calcula un rango para cada fila por grupo y luego filtra las filas más recientes como con rank = 1
MANIFESTACIÓN
Aquí está la demostración visual del rango no para cada fila para una mejor comprensión
La consulta anterior fallará y devolverá más de 1 filas para la situación anterior. Para encubrir esta situación, será necesario otro criterio / parámetro / columna para decidir qué fila se debe tomar y que corresponde a la situación anterior. Al ver el conjunto de datos de muestra, supongo que hay una columna de clave principal
id
que debe establecerse en incremento automático. Entonces, podemos usar esta columna para elegir la fila más reciente ajustando la misma consulta con la ayuda deCASE
declaraciones comoMANIFESTACIÓN
La consulta anterior elegirá la fila con la identificación más alta entre los mismos
datetime
valoresdemostración visual para el rango no para cada fila
fuente
¿Por qué no usar: SELECT home, MAX (datetime) AS MaxDateTime, player, resource FROM topten GROUP BY home ¿Me perdí algo?
fuente
expected
resultado en MySQL versión 5.6 ybefore
dudo mucho que se comporte de otra manera en MySQL versión 5.7 yafter
.Prueba esto
Saludos K
fuente
max(datetime)
esdatetime
. ¿No hará ningún problema?datetime
selecciona el más alto ?esta es la consulta que necesitas:
fuente
@Michae La respuesta aceptada funcionará bien en la mayoría de los casos, pero falla para una de las siguientes.
En caso de que haya 2 filas con HomeID y Datetime iguales, la consulta devolverá ambas filas, no HomeID diferente según sea necesario, para eso agregar Distinct en la consulta como se muestra a continuación.
fuente
Espero que debajo de la consulta se obtenga el resultado deseado:
fuente