为每个 ID 选择每个月的最后一条记录

Posted

技术标签:

【中文标题】为每个 ID 选择每个月的最后一条记录【英文标题】:Select last record of each month for each ID 【发布时间】:2021-01-23 07:12:15 【问题描述】:

我正在尝试为每个 ID 提取每个月的最后一条记录。

下面是我请求的表格:

myTable
ID  date         data
1   2020-08-27   a
1   2020-08-28   b
1   2020-09-30   c
2   2020-08-29   d
2   2020-09-30   e

因此,我想得到以下信息:

output
ID  date         data
1   2020-08-28   b
1   2020-09-30   c
2   2020-08-29   d
2   2020-09-30   e

这里的“复杂性”是每个ID每个月的最后一条记录可能不一样。

到目前为止,我只能通过以下请求在数据库中获取每个月最后一个日期的所有可用记录:

SELECT ID, date, data
from myTable
and date in (SELECT max(date) FROM myTable GROUP BY strftime('%Y-%m', date))

这给了我这个

wrong output
ID  date         data
1   2020-09-30   c
2   2020-08-29   d
2   2020-09-30   e

【问题讨论】:

【参考方案1】:

您可以使用相关子查询进行过滤:

select t.*
from mytable t
and date = (
    select max(t1.date) 
    from mytable t1 
    where strftime('%Y-%m', t1.date) = strftime('%Y-%m', t.date) and t1.id = t.id
)

另一种方法使用窗口函数:

select *
from (
    select t.*,
        rank() over(partition by id, strftime('%Y-%m', date) order by date desc) rn
    from mytable t
) t
where rn = 1

【讨论】:

非常感谢您的回答。使用 windows 选项的第二个选项效果很好。第一个虽然没有,但乍一看更吸引人,因为我不知道 windows 功能。 @GMB 您的两个查询都不起作用:strftime('%y-%m', date) 针对 SQLite 中的任何有效日期返回 null:db-fiddle.com/f/q5b2YyqvFz1E1ZfLK5vKT7/0 此外,您的第二个查询是在我的回答之后发布的,因为最初您只发布了第一个查询,您稍后添加了第二个查询,尽管编辑时间戳不会在问题的初始发布后这样的排序时间内保存编辑。 @forpas:好的,我将%y 固定为%Y(我认为这是一个错字...),谢谢。这就是为什么你的答案应该被接受的一个很好的理由(而不是讨论发布时间戳)。【参考方案2】:

使用 ROW_NUMBER() 窗口函数:

SELECT ID, date, data
FROM (
  SELECT *,
    ROW_NUMBER() OVER (PARTITION BY ID, strftime('%Y%m', date) ORDER BY date DESC) rn
  FROM myTable 
)
WHERE rn = 1

【讨论】:

非常感谢,这太棒了。我不知道windows功能。

以上是关于为每个 ID 选择每个月的最后一条记录的主要内容,如果未能解决你的问题,请参考以下文章

获取每个月的最后一条记录

获取每个 ID 的最后一条记录

有重复组时选择最后一组的第一条记录

MySQL:如何在 SQL 查询中为每个结果插入一条记录?

获取几个月的最新记录并使用 Oracle PL-SQL 为每个 ID 汇总其值

获取每个月最后一条记录的值(Django)