我正在尝试从表中获取ip,用户和最新时间戳,该表可能包含用户的当前ip和一个或多个先前的ips。我想为每个用户提供一行,其中包含最新的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。
答案 0 :(得分:93)
试试这个:
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
答案 1 :(得分:31)
使用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;
答案 2 :(得分:8)
这样的事情:
select *
from User U1
where time_stamp = (
select max(time_stamp)
from User
where username = U1.username)
应该这样做。
答案 3 :(得分:3)
上述两个答案都假设每个用户和time_stamp只有一行。根据应用程序和time_stamp的粒度,这可能不是一个有效的假设。如果您需要为给定用户处理time_stamp的关系,则需要扩展上面给出的答案之一。
在一个查询中写这个需要另一个嵌套的子查询 - 事情会变得更加混乱,性能可能会受到影响。
我本来希望将此添加为评论,但我还没有50个声誉,所以很抱歉发布新答案!
答案 4 :(得分:2)
还不能发表评论,但@Cristi S的答案对我有用。
在我的场景中,我需要在Lowest_Offers中仅保留所有product_ids中最近的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;
答案 5 :(得分:0)
我一直在使用它,因为我正在从另一个表返回结果。虽然我试图避免嵌套连接,如果它有助于减少一步。那好吧。它返回相同的东西。
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