Consulta SQL para obtener la fila más reciente para cada instancia de una clave determinada

StackOverflow https://stackoverflow.com/questions/1140064

Pregunta

Estoy intentando obtener la IP, el usuario y la marca de tiempo más reciente de una tabla que puede contener tanto la IP actual de un usuario como una o más IP anteriores.Me gustaría una fila para cada usuario que contenga la IP más reciente y la marca de tiempo asociada.Entonces, si una tabla se ve así:

username      |  ip      |  time_stamp  
--------------|----------|--------------  
ted           | 1.2.3.4  | 10  
jerry         | 5.6.6.7  | 12  
ted           | 8.8.8.8  | 30  

Esperaría que el resultado de la consulta fuera:

jerry    |  5.6.6.7   |  12
ted      |  8.8.8.8   |  30  

¿Puedo hacer esto en una única consulta SQL?Por si importa, el DBMS es Postgresql.

¿Fue útil?

Solución

Prueba esto:

Select u.[username]
      ,u.[ip]
      ,q.[time_stamp]
From [users] As u
Inner Join (
    Select [username]
          ,max(time_stamp) as [time_stamp]
    From [users]
    Group By [username]) As [q]
On u.username = q.username
And u.time_stamp = q.time_stamp

Otros consejos

solución elegante agradable con la función de ventana ROW_NUMBER (con el apoyo de PostgreSQL - ver en SQL violín ):

SELECT username, ip, time_stamp FROM (
 SELECT username, ip, time_stamp, 
  ROW_NUMBER() OVER (PARTITION BY username ORDER BY time_stamp DESC) rn
 FROM Users
) tmp WHERE rn = 1;

Algo como esto:

select * 
from User U1
where time_stamp = (
  select max(time_stamp) 
  from User 
  where username = U1.username)

debería hacerlo.

Las dos respuestas anteriores se supone que sólo tiene una fila para cada usuario y indicación_hora. Dependiendo de la aplicación y la granularidad de su indicación_hora esto puede no ser una suposición válida. Si usted necesita para hacer frente a los lazos de indicación_horaria para un usuario determinado, que había necesidad de ampliar una de las respuestas dadas anteriormente.

Para escribir esto en una consulta requeriría otro sub-consulta anidada -. Las cosas van a empezar a recibir más desordenado y el rendimiento pueden sufrir

Me hubiera gustado haber añadido esto como un comentario, pero que todavía no tienen 50 reputación tan mal por la publicación como una nueva respuesta!

Todavía no puedo publicar comentarios, pero la respuesta de @Cristi S me funciona de maravilla.

En mi escenario, necesitaba conservar solo los 3 registros más recientes en Lowest_Offers para todos los product_ids.

Necesita reelaborar su SQL para eliminarlo; pensé que estaría bien, pero la sintaxis es incorrecta.

DELETE from (
SELECT product_id, id, date_checked,
  ROW_NUMBER() OVER (PARTITION BY product_id ORDER BY date_checked DESC) rn
FROM lowest_offers
) tmp WHERE > 3;

He estado usando esto porque voy a volver resultados de otra tabla. Aunque yo estoy tratando de evitar el anidado si ayuda w / un paso menos. Oh bien. Devuelve la misma cosa.

select
users.userid
, lastIP.IP
, lastIP.maxdate

from users

inner join (
    select userid, IP, datetime
    from IPAddresses
    inner join (
        select userid, max(datetime) as maxdate
        from IPAddresses
        group by userid
        ) maxIP on IPAddresses.datetime = maxIP.maxdate and IPAddresses.userid = maxIP.userid
    ) as lastIP on users.userid = lastIP.userid
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top