2009-06-26 11 views
45

Estoy creando un módulo de placa de estado para mi equipo de proyecto. La placa de estado permite al usuario establecer su estado como de entrada o salida y también pueden proporcionar una nota. Yo estaba pensando en almacenar toda la información en una sola tabla ... y el ejemplo de los datos siguen:Crear una consulta SQL para recuperar los registros más recientes

Date    User   Status Notes 
------------------------------------------------------- 
1/8/2009 12:00pm B.Sisko  In  Out to lunch  
1/8/2009 8:00am B.Sisko  In 
1/7/2009 5:00pm B.Sisko  In  
1/7/2009 8:00am B.Sisko  In  
1/7/2009 8:00am K.Janeway In 
1/5/2009 8:00am K.Janeway In  
1/1/2009 8:00am J.Picard  Out  Vacation 

me gustaría consultar los datos y devolver el estado más reciente para cada usuario, en este caso, mi consulta arrojaría los siguientes resultados:

Date    User   Status Notes 
------------------------------------------------------- 
1/8/2009 12:00pm B.Sisko  In  Out to lunch  
1/7/2009 8:00am K.Janeway In 
1/1/2009 8:00am J.Picard  Out  Vacation 

¿Intento descubrir el TRANSACT-SQL para que esto suceda? Cualquier ayuda sería apreciada.

+2

Jajaja ... tabla de tiempos de la Flota. –

Respuesta

63

Agregue en una tabla derivada de subconsultas y luego únase a ella.

Select Date, User, Status, Notes 
    from [SOMETABLE] 
    inner join 
    (
     Select max(Date) as LatestDate, [User] 
     from [SOMETABLE] 
     Group by User 
    ) SubMax 
    on [SOMETABLE].Date = SubMax.LatestDate 
    and [SOMETABLE].User = SubMax.User 
+4

Esto se llama una tabla derivada. – SurroundedByFish

+0

funciona perfectamente :-) – Fox

+5

tener cuidado si la tabla derivada termina con duplicados para {LatestDate, Usuario} – alphadogg

41

otra manera, esto va a escanear la tabla sólo una vez en lugar de dos veces si se utiliza una subconsulta

único servidor SQL 2005 y hasta

select Date, User, Status, Notes 
from (
     select m.*, row_number() over (partition by user order by Date desc) as rn 
     from [SOMETABLE] m 
    ) m2 
where m2.rn = 1; 
+0

magia, yo era capaz de resolver la consulta complicado que implica unirse a 3 mesas y seleccionando sólo la última entrada para cada tipo basado en el código . ¡Gracias! – Sopuli

+1

Esto tiene el mismo costo en el plan de ejecución que la respuesta aceptada, pero cuando necesita agrupar por varias columnas, por ejemplo orgID, Mes, Año, esta respuesta es semánticamente más clara. – gooddadmike

+0

esto selecciona aleatoriamente el registro de todos los registros iguales primero según el orden. –

7

La tabla derivada quiere trabajar, pero si esto es SQL 2005, un CTE y ROW_NUMBER podrían ser más limpio:

WITH UserStatus (User, Date, Status, Notes, Ord) 
as 
(
SELECT Date, User, Status, Notes, 
    ROW_NUMBER() OVER (PARTITION BY User ORDER BY Date DESC) 
FROM [SOMETABLE] 
) 

SELECT User, Date, Status, Notes from UserStatus where Ord = 1 

esto también facilitaría las dis juego de los estados x más recientes de cada usuario.

4

Otra manera fácil:

SELECT Date, User, Status, Notes 
FROM Test_Most_Recent 
WHERE Date in (SELECT MAX(Date) from Test_Most_Recent group by User) 
+3

¿No saldrá mal esta consulta si dos usuarios actualizan su estado al mismo tiempo, pero esa no es la actividad más reciente para uno de ellos? – SooDesuNe

+0

Mahesh, necesita actualizar su respuesta teniendo en cuenta el comentario de @SoDesDes. –

+0

No utilice SELECCIONES en las cláusulas WHERE si puede evitarlo. A menos que sea una cosa de una vez que necesita buscar. Si esto sucede en un proceso almacenado, aumenta enormemente el tiempo para devolver los resultados. Especialmente en mesas grandes. –

Cuestiones relacionadas