从数据库中检索每个用户的倒数第二条记录

Posted

技术标签:

【中文标题】从数据库中检索每个用户的倒数第二条记录【英文标题】:Retrieve the second last record for each user from the database 【发布时间】:2012-09-07 20:45:32 【问题描述】:

我有一个包含用户名、更新日期和状态的表格,如下所示:

名称 |更新_on |状态

akg     29-NOV-10       Active
akg     13-JAN-12       NonActive
akg     10-MAR-12       Active
ems     23-JUL-12       NonActive
ems     10-SEP-10       Active
tkp     10-SEP-10       NonActive
tkp     13-DEC-10       Active
tkp     02-JUL-12       NonActive
tkp     24-SEP-10       Active
aron    12-JAN-11       NonActive
aron    07-NOV-11       Active
aron    25-JUN-12       NonActive

在此表中,每次我们更改状态时都会更新用户状态(即username 可以有许多条目,如表中所示。

我想要每个用户的第二个最后更新记录。即对于上表,结果应该是:

名称 |更新_on |状态

akg     13-JAN-12       NonActive
ems     10-SEP-10       Active
tkp     13-DEC-10       Active
aron    07-NOV-11       Active

我真的很困惑,因为我想获得每个用户的记录。

是否有任何查询可以用于此?

谢谢

【问题讨论】:

倒数第二条记录还是第二条记录? 当给定用户只有一条记录时会发生什么? @koderoid: 每个用户的第二次最后更新记录。 @Gerard Yin:我们可以忽略这种情况 【参考方案1】:

你可以试试,虽然有点冗长,但很有效:

SELECT
  name,
  max(Updated_on) as Updated_on,
  STATUS
FROM userstatus a
  WHERE (name, Updated_on) not in
  (select name, max(Updated_on) FROM userstatus group by name)
group by name, status
HAVING UPDATED_ON =
  (SELECT MAX(UPDATED_ON) FROM userstatus b where a.name = b.name
   and (b.name, b.Updated_on) not in
  (select name, max(Updated_on) FROM userstatus group by name)
  group by name);

Sqlfiddle

【讨论】:

【参考方案2】:
SELECT * FROM (
  SELECT
    rounda.*
  FROM
    userstatus AS rounda
    INNER JOIN userstatus AS roundb
      ON rounda.name=roundb.name
      AND rounda.Updated_on<roundb.Updated_On
  ORDER BY Updated_on DESC
) AS baseview
GROUP BY name

见sqlfiddle

【讨论】:

此查询仅按一个字段分组。这是使用 mysql 的一个称为“隐藏列”的功能。 MySQL保证任何结果。它甚至不能保证非聚合列中的所有值都来自同一条记录。 @GordonLinoff 虽然这一般是正确的,但在这个特殊情况中不是正确的:它是1的组合。)内部查询被解析为已排序的临时表和 2.) GROUP BY 仅由内部临时表的行号驱动。这保证了分组将选择执行时看到的第一个值作为隐藏列的字段值。基本上我(ab)使用 MySQL 查询优化器的缺陷来实现确定性行为。漂亮吗?不,它可靠吗?是的。 文档非常清楚这些值是任意且不确定的 (dev.mysql.com/doc/refman/5.5/en/group-by-hidden-columns.html)。您能否提供一个参考,说明在带有 order by 子句的子查询的情况下值是确定的?【参考方案3】:

当您使用 Oracle 标记此(也)时:

select name, updated_on, status
from (
  select name, updated_on, status,
         row_number() over (partition by name order by updated_on desc) as rn,
         count(*) over (partition by name) as max_rn
  from userstatus
) 
where rn = max_rn - 1 
   or max_rn = 1;

这实际上适用于各种 DBMS(包括 Oracle)——只是不适用于 MySQL。

【讨论】:

对于这个查询,我得到一个错误,下面给出 ORA-00909:无效的参数数量 00909。00000 -“无效的参数数量”......我在第 5 行得到这个(在那个计数上() 行) @anandkk:我忘记了count(*)中的*

以上是关于从数据库中检索每个用户的倒数第二条记录的主要内容,如果未能解决你的问题,请参考以下文章

Discord Bot - 如何删除倒数第二条最近的消息?

将第二条记录添加到数据库后,代号为一个 Sqlite 问题

奇怪的错误,collectionView 视图滚动到倒数第二条消息,当试图滚动到底部

在 R 中,当 ID 不唯一时,如何从每个 ID 的数据框中获取倒数第二行? [复制]

按组中第二条记录的数据对记录组进行排序

SQL语句如何查询倒数第二项数据