在postgresql中按月和年分组查询结果

Fre*_*chi 133 sql postgresql

我在Postgres服务器上有以下数据库表:

id      date          Product Sales
1245    01/04/2013    Toys    1000     
1245    01/04/2013    Toys    2000
1231    01/02/2013    Bicycle 50000
456461  01/01/2014    Bananas 4546
Run Code Online (Sandbox Code Playgroud)

我想创建一个查询,给出SUM了的Sales按月份和年份如下列并对结果进行分组:

Apr    2013    3000     Toys
Feb    2013    50000    Bicycle
Jan    2014    4546     Bananas
Run Code Online (Sandbox Code Playgroud)

有一个简单的方法吗?

Bur*_*lan 263

我无法相信接受的答案有这么多的赞成 - 这是一种可怕的方法.

使用date_trunc,这是正确的方法:

   SELECT date_trunc('month', txn_date) AS txn_month, sum(amount) as monthly_sum
     FROM yourtable
 GROUP BY txn_month
Run Code Online (Sandbox Code Playgroud)

这是不好的做法,但如果你使用,你可能会被原谅

 GROUP BY 1
Run Code Online (Sandbox Code Playgroud)

在一个非常简单的查询中.

你也可以使用

 GROUP BY date_trunc('month', txn_date)
Run Code Online (Sandbox Code Playgroud)

如果您不想选择日期.

  • 不幸的是,`date_trunc`的输出不是提问者所期望的:`select date_trunc('month',timestamp'2001-02-16 20:38:40')`=>`2001-02-01 00:00:00 `. (4认同)
  • 为什么突然使用时间,而原始数据只是一个日期?我只想要年+月以可读的方式,但顺序正确。 (3认同)
  • 我同意这种方法更好.我不确定,但我认为它也更有效率,因为只有一个分组而不是两个.如果你需要重新格式化日期,你可以使用其他答案中描述的方法:`to_char(date_trunc('month',txn_date),'YY-Mon') (2认同)
  • 是的,接受答案的票数令人难以置信。`date_trunc` 正是为此目的而创建的。没有理由创建两列 (2认同)
  • 非常好!这是一个很好的答案,特别是因为您也可以订购。点赞! (2认同)
  • 另一个例子,最高投票的答案应该出现在接受的答案之前 (2认同)
  • 如果您能解释为什么接受的答案是“一种可怕的方法”,那就太好了,因为这对我来说并不明显。 (2认同)

bma*_*bma 186

select to_char(date,'Mon') as mon,
       extract(year from date) as yyyy,
       sum("Sales") as "Sales"
from yourtable
group by 1,2
Run Code Online (Sandbox Code Playgroud)

应Radu的要求,我将解释该查询:

to_char(date,'Mon') as mon, :将"日期"属性转换为月份的缩写形式的定义格式.

extract(year from date) as yyyy :Postgresql的"提取"功能用于从"日期"属性中提取YYYY年份.

sum("Sales") as "Sales" :SUM()函数将所有"Sales"值相加,并提供区分大小写的别名,使用双引号保持区分大小写.

group by 1,2:GROUP BY函数必须包含SELECT列表中不属于聚合的所有列(也就是所有不在SUM/AVG/MIN/MAX等函数内的列).这告诉查询应该为每个唯一的列组合应用SUM(),在这种情况下,列是月和年列."1,2"部分是简写而不是使用列别名,尽管最好使用完整的"to_char(...)"和"extract(...)"表达式来提高可读性.

  • 竖起大拇指教我分组1,2的快捷方式! (31认同)
  • 我不认为在没有解释的情况下给出答案是一个非常好的主意,特别是对于初学者.你应该已经解释了你的答案背后的逻辑,也许至少有一点(尽管对我们其他人来说这似乎很简单和直接). (3认同)
  • @rogerdpack,`date_trunc` 的输出并不是提问者想要的:`select date_trunc('month', timestamp '2001-02-16 20:38:40')::date` => `2001-02- 01` (2认同)
  • 我喜欢在 `group by` 子句中使用 `date_trunc` 的想法。 (2认同)
  • 可能出现“字段必须在 group by 子句中”的问题...最好使用 OVER (PARTITION BY)。 (2认同)

mgo*_*ser 29

to_char 实际上让你一举拔出年份和月份!

select to_char(date('2014-05-10'),'Mon-YY') as year_month; --'May-14'
select to_char(date('2014-05-10'),'YYYY-MM') as year_month; --'2014-05'
Run Code Online (Sandbox Code Playgroud)

或者在上述用户示例的情况下:

select to_char(date,'YY-Mon') as year_month
       sum("Sales") as "Sales"
from some_table
group by 1;
Run Code Online (Sandbox Code Playgroud)

  • 如果您的表中有相当数量的数据,我会建议强烈反对这样做.执行group by时,这比执行`date_trunc`方法要差**.在DB上进行试验我很方便,在一个有270k行的表上,date_trunc方法的速度是TO_CHAR的两倍多 (3认同)
  • 您仍然可以这样做 - 只需通过按查询“包装”组来将格式设置为单独的步骤。例如 SELECT to_char(d, 'YYYY-DD') FROM (SELECT date_trunc('month', d) AS "d" FROM tbl) AS foo。两全其美! (2认同)
  • 这个解决方案简单而优雅。我喜欢它,在我的情况下它足够快。谢谢你的回答! (2认同)

jia*_*ian 12

为什么不直接使用date_part函数呢?https://www.postgresql.org/docs/8.0/functions-datetime.html

SELECT date_part('year', txn_date) AS txn_year,
       date_part('month', txn_date) AS txn_month,
       sum(amount) as monthly_sum
FROM payment
GROUP BY txn_year, txn_month
order by txn_year;
Run Code Online (Sandbox Code Playgroud)


小智 6

还有另一种方法可以使用 postgres 中的 date_part() 函数来实现结果。

 SELECT date_part('month', txn_date) AS txn_month, date_part('year', txn_date) AS txn_year, sum(amount) as monthly_sum
     FROM yourtable
 GROUP BY date_part('month', txn_date)
Run Code Online (Sandbox Code Playgroud)

谢谢


Luc*_*uhn 5

看一下本教程的示例 6) -> https://www.postgresqltutorial.com/postgresql-group-by/

您需要在 GROUP BY 上调用该函数,而不是调用在 select 上创建的虚拟属性的名称。我正在按照上面建议的所有答案进行操作,但出现了错误column 'year_month' does not exist

对我有用的是:

SELECT 
    date_trunc('month', created_at), 'MM/YYYY' AS month
FROM 
    "orders"  
GROUP BY 
    date_trunc('month', created_at)
Run Code Online (Sandbox Code Playgroud)