development

주어진 키의 각 인스턴스에 대한 최신 행을 가져 오는 SQL 쿼리

big-blog 2020. 11. 20. 09:12
반응형

주어진 키의 각 인스턴스에 대한 최신 행을 가져 오는 SQL 쿼리


사용자의 현재 IP와 하나 이상의 이전 IP를 모두 포함 할 수있는 테이블에서 IP, 사용자 및 최신 타임 스탬프를 가져 오려고합니다. 가장 최근의 IP 및 관련 타임 스탬프를 포함하는 각 사용자에 대해 하나의 행을 원합니다. 따라서 테이블이 다음과 같은 경우 :

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

쿼리 출력은 다음과 같을 것으로 예상됩니다.

jerry    |  5.6.6.7   |  12
ted      |  8.8.8.8   |  30  

단일 SQL 쿼리에서이 작업을 수행 할 수 있습니까? 중요한 경우 DBMS는 Postgresql입니다.


이 시도:

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

ROW_NUMBER 창 기능이있는 멋진 솔루션 (PostgreSQL에서 지원 -SQL Fiddle 참조 ) :

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;

이 같은:

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

해야합니다.


위의 두 답변 모두 각 사용자 및 time_stamp에 대해 하나의 행만 있다고 가정합니다. 애플리케이션 및 time_stamp의 세분성에 따라 이것은 유효한 가정이 아닐 수 있습니다. 특정 사용자에 대한 time_stamp의 관계를 처리해야하는 경우 위에 제공된 답변 중 하나를 확장해야합니다.

이것을 하나의 쿼리로 작성하려면 또 다른 중첩 하위 쿼리가 필요합니다. 일이 더 지저분 해지고 성능이 저하 될 수 있습니다.

나는 이것을 댓글로 추가하고 싶었지만 아직 50 개의 평판이 없어서 새로운 답변으로 게시해서 죄송합니다!


아직 댓글을 게시 할 수 없지만 @Cristi S의 답변은 나를 위해 대접을 받았습니다.

내 시나리오에서는 모든 product_id에 대해 Lowest_Offers에 가장 최근의 3 개 레코드 만 유지해야했습니다.

삭제하려면 SQL을 재 작업해야합니다. 이것이 괜찮을 것이라고 생각했지만 구문이 잘못되었습니다.

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;

I've been using this because I'm returning results from another table. Though I'm trying to avoid the nested join if it helps w/ one less step. Oh well. It returns the same thing.

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

참고URL : https://stackoverflow.com/questions/1140064/sql-query-to-get-most-recent-row-for-each-instance-of-a-given-key

반응형