如何在Postgres中按年月按最大(日期)组获取行?

Posted

技术标签:

【中文标题】如何在Postgres中按年月按最大(日期)组获取行?【英文标题】:How to get rows by max(date) group by Year-Month in Postgres? 【发布时间】:2021-08-17 02:31:18 【问题描述】:

我正在将报告从 mysql 迁移到 Postgres,我正在尝试按年和月获取每个类别组的最新记录,在 MySQL 中它看起来像这样:

 select Category,
        max(DATECOL) AS Date
 from Table
 group by Category, date_format(DATECOL,'%Y-%m')
 order by DATECOL desc;

+----------+------------+
| Category | Date       |
+----------+------------+
| A        | 2021-05-27 |
+----------+------------+
| B        | 2021-05-27 |
+----------+------------+
| A        | 2021-04-30 |
+----------+------------+
| B        | 2021-04-30 |
+----------+------------+
| A        | 2021-03-31 |
+----------+------------+
| B        | 2021-03-31 |
+----------+------------+ 

但是当我在 Postgres 中尝试以下操作时,它会给我一个 "Must include DATECOL in GROUP BY" 错误消息,当我包含 DATECOL 时,它只会返回所有可能的日期。有没有办法在 Postgres 中获取每个类别的最大记录? .这是我在 Postgres 中尝试过的,它返回 "Must include DATECOL in GROUP BY" 错误

 select Category,
        max(DATECOL) AS DATE
 from Table
 group by Category, concat(EXTRACT(year from DATECOL),'-', EXTRACT(month from DATECOL) )
 order by DATECOL desc;

【问题讨论】:

不,这在 MySQL 中不起作用,因为它只是返回随机结果而不是拒绝无效查询。 【参考方案1】:

解决greatest-n-per-group的一种方法是使用窗口函数:Postgres you

select category, 
       DateCol 
from (
  select category, 
         DateCol,
         row_number() over (partition by category, date_trunc('month', DateCol ) 
                            order by DateCol desc) as rn
  from table
) t
where rn = 1;

【讨论】:

【参考方案2】:

要获取每个类别月份的最新日期,只需按两者分组即可。使用to_char() 随意格式化:

SELECT category
     , to_char(datecol, 'YYYY-MM') AS mon
     , max(datecol) AS max_date
FROM   tbl
GROUP  BY 2, 1
ORDER  BY 2 DESC, 1;

mon 不必在SELECT 列表中。但是,当然,您不能使用序数位置作为速记:

SELECT category
     , max(datecol) AS max_date
FROM   tbl
GROUP  BY to_char(datecol, 'YYYY-MM'), category
ORDER  BY to_char(datecol, 'YYYY-MM') DESC, category;

缺点:格式化文本可能无法正确排序(当然,YYYY-MM 通常没有问题)。对于大桌子,date_trunc() 更便宜一些。而且由于我们甚至没有显示它:

SELECT category
     , max(datecol) AS max_date
FROM   tbl
GROUP  BY date_trunc('month', datecol), 1
ORDER  BY date_trunc('month', datecol) DESC, 1;

以任何您喜欢的方式显示和格式化:

SELECT category
     , to_char(date_trunc('month', datecol), 'YYYY-MM') AS mon
     , max(datecol) AS max_date
FROM   tbl
GROUP  BY date_trunc('month', datecol), category
ORDER  BY date_trunc('month', datecol) DESC, category;

您必须重复 GROUP BY 表达式(除非您将其推送到子查询中),即使这对 to_char() 没有任何影响。

相关:

Sorting months while im converting them to text

【讨论】:

感谢您的及时回复! So do you have your answer?

以上是关于如何在Postgres中按年月按最大(日期)组获取行?的主要内容,如果未能解决你的问题,请参考以下文章

SQL中按日期进行查询,如何截取日期进行查询

在Impala中按组减去最大,最小日期

在mysql和php中按日期范围分组

如何在 woocommerce 中按日期获取用户订单?

如何在codeigniter中按日期降序获取订单

在雪花中按日期聚合数据组