ultimo ultima seleccionar registro reciente rango por obtener mayor mas grupo fechas fecha consulta cada buscar mysql sql greatest-n-per-group

mysql - ultima - Seleccione la fila con la fecha más reciente por usuario



sql seleccionar registro mayor fecha (8)

Basado en @TMS answer, me gusta porque no hay necesidad de subconsultas, pero creo que omitir la parte ''OR'' será suficiente y mucho más simple de entender y leer.

SELECT t1.* FROM lms_attendance AS t1 LEFT JOIN lms_attendance AS t2 ON t1.user = t2.user AND t1.time < t2.time WHERE t2.user IS NULL

Si no está interesado en filas con tiempos nulos, puede filtrarlas en la cláusula WHERE :

SELECT t1.* FROM lms_attendance AS t1 LEFT JOIN lms_attendance AS t2 ON t1.user = t2.user AND t1.time < t2.time WHERE t2.user IS NULL and t1.time IS NOT NULL

Tengo una tabla ("lms_attendance") de las horas de check-in y out de los usuarios que se ve así:

id user time io (enum) 1 9 1370931202 out 2 9 1370931664 out 3 6 1370932128 out 4 12 1370932128 out 5 12 1370933037 in

Intento crear una vista de esta tabla que muestre solo el registro más reciente por ID de usuario, mientras me da el valor de "entrada" o "salida", así que algo así como:

id user time io 2 9 1370931664 out 3 6 1370932128 out 5 12 1370933037 in

Estoy bastante cerca hasta ahora, pero me di cuenta de que las vistas no aceptarán subquerys, lo que hace que sea mucho más difícil. La consulta más cercana que recibí fue:

select `lms_attendance`.`id` AS `id`, `lms_attendance`.`user` AS `user`, max(`lms_attendance`.`time`) AS `time`, `lms_attendance`.`io` AS `io` from `lms_attendance` group by `lms_attendance`.`user`, `lms_attendance`.`io`

Pero lo que obtengo es:

id user time io 3 6 1370932128 out 1 9 1370931664 out 5 12 1370933037 in 4 12 1370932128 out

Que está cerca, pero no es perfecto. Sé que el último grupo no debería estar allí, pero sin él, devuelve el tiempo más reciente, pero no con su valor relativo de IO.

¿Algunas ideas? ¡Gracias!


Consulta:

SQLFIDDLEExample

SELECT t1.* FROM lms_attendance t1 WHERE t1.time = (SELECT MAX(t2.time) FROM lms_attendance t2 WHERE t2.user = t1.user)

Resultado:

| ID | USER | TIME | IO | -------------------------------- | 2 | 9 | 1370931664 | out | | 3 | 6 | 1370932128 | out | | 5 | 12 | 1370933037 | in |

Solución que funcionará todo el tiempo:

SQLFIDDLEExample

SELECT t1.* FROM lms_attendance t1 WHERE t1.id = (SELECT t2.id FROM lms_attendance t2 WHERE t2.user = t1.user ORDER BY t2.id DESC LIMIT 1)


Esto funcionó para mí:

SELECT user, time FROM ( SELECT user, time FROM lms_attendance --where clause ) AS T WHERE (SELECT COUNT(0) FROM table WHERE user = T.user AND time > T.time) = 0 ORDER BY user ASC, time DESC


No es necesario intentar reinventar la rueda, ya que este es el problema común de greatest-n-per-group . Muy buena solución se presenta .

Prefiero la solución más simple ( ver SQLFiddle, Justin actualizado ) sin subconsultas (por lo tanto, fácil de usar en las vistas):

SELECT t1.* FROM lms_attendance AS t1 LEFT OUTER JOIN lms_attendance AS t2 ON t1.user = t2.user AND (t1.time < t2.time OR (t1.time = t2.time AND t1.Id < t2.Id)) WHERE t2.user IS NULL

Esto también funciona en un caso donde hay dos registros diferentes con el mismo valor más grande dentro del mismo grupo, gracias al truco con (t1.time = t2.time AND t1.Id < t2.Id) . Todo lo que hago aquí es asegurar que en caso de que dos registros del mismo usuario tengan el mismo tiempo, solo se elija uno. En realidad, no importa si el criterio es Id u otra cosa; básicamente, cualquier criterio que se garantice como único haría el trabajo aquí.


Posiblemente puede hacer un grupo por usuario y luego ordenar por tiempo desc. Algo como lo siguiente

SELECT * FROM lms_attendance group by user order by time desc;


Prueba esta consulta:

select id,user, max(time), io FROM lms_attendance group by user;


Ya resuelto, pero solo para el registro, otro enfoque sería crear dos vistas ...

CREATE TABLE lms_attendance (id int, user int, time int, io varchar(3)); CREATE VIEW latest_all AS SELECT la.user, max(la.time) time FROM lms_attendance la GROUP BY la.user; CREATE VIEW latest_io AS SELECT la.* FROM lms_attendance la JOIN latest_all lall ON lall.user = la.user AND lall.time = la.time; INSERT INTO lms_attendance VALUES (1, 9, 1370931202, ''out''), (2, 9, 1370931664, ''out''), (3, 6, 1370932128, ''out''), (4, 12, 1370932128, ''out''), (5, 12, 1370933037, ''in''); SELECT * FROM latest_io;

Haga clic aquí para verlo en acción en SQL Fiddle


select b.* from (select `lms_attendance`.`user` AS `user`, max(`lms_attendance`.`time`) AS `time` from `lms_attendance` group by `lms_attendance`.`user`) a join (select * from `lms_attendance` ) b on a.user = b.user and a.time = b.time