SQL查询以获取给定键的每个实例的最新行

Posted

技术标签:

【中文标题】SQL查询以获取给定键的每个实例的最新行【英文标题】:SQL query to get most recent row for each instance of a given key 【发布时间】:2010-11-11 12:32:14 【问题描述】:

我正在尝试从一个表中获取 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。

【问题讨论】:

【参考方案1】:

还不能发布 cmets,但 @Cristi S 的回答对我来说是一种享受。

在我的场景中,我只需要在 Lowest_Offers 中为所有 product_id 保留最近的 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;

【讨论】:

更正 SQL:从 Lowest_Offer 中删除 id in (SELECT id FROM (SELECT product_id, id, date_checked, ROW_NUMBER() OVER (PARTITION BY product_id ORDER BY date_checked DESC) rn FROM Lowest_Offer) tmp WHERE rn> 3) 我认为这需要一个 desc 索引而不是时间戳【参考方案2】:

带有 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;

【讨论】:

这是最好的答案,因为它不涉及嵌套查询的连接。唯一的问题是它需要在密钥中包含 [ip] 以及每个问题的用户名。 这是最高效的解决方案。使用 POSTGRES 解释分析工具尝试了这些解决方案,这是最好的。优秀的代码【参考方案3】:

我一直在使用它,因为我要从另一个表返回结果。虽然我试图避免嵌套连接,如果它有助于少一步。那好吧。它返回相同的东西。

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

【讨论】:

我认为这是上述用户响应的答案【参考方案4】:

以上两个答案都假设每个用户和时间戳只有一行。根据应用程序和 time_stamp 的粒度,这可能不是一个有效的假设。如果您需要处理给定用户的 time_stamp 关系,则需要扩展上面给出的答案之一。

在一个查询中写这个需要另一个嵌套的子查询 - 事情会开始变得更加混乱,性能可能会受到影响。

我很想将此作为评论添加,但我还没有 50 名声望,所以很抱歉作为新答案发布!

【讨论】:

“以上都...”不是开始回答的好方法。我怎么知道上面的答案是否是您所指的答案?答案可以根据分数以不同的顺序出现。 Rob,我不认为你在告诉他一些他不知道的事情。他不能发表评论,他所指的答案显然有缺陷。更重要的是传播知识还是批评文本的放置位置?【参考方案5】:

类似这样的:

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

应该这样做。

【讨论】:

如果time_stamp 是唯一的并且您不能假设,那将起作用。【参考方案6】:

试试这个:

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

【讨论】:

我在正确的轨道上,但我无法完全正确地加入。这成功了。谢谢! 这在 SQL Server 中有效吗?在类似的数据上尝试了完全相同的事情,但我得到了每个“ip”的一行以及最近的时间戳。 针对 HANA 表使用,这会产生预期为 1 的多行。 HANA 有很多与大多数流行的 SQL 引擎不一样的东西。

以上是关于SQL查询以获取给定键的每个实例的最新行的主要内容,如果未能解决你的问题,请参考以下文章

查找 sql 查询以获取每个分组的最新关联日期

SQL 查询以获取每个位置的“最新”值

Sql 查询以获取最多 10 条的最新记录并按提到行排名的字段排序 [关闭]

SQL 查询以获取特定对象的最新操作/更新

MySQL中最新订单状态的SQL查询

SQL 查询以显示表中包含数据的最新行,或为空