我在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
我想创建一个查询,给出Sales列的SUM,并按月和年将结果分组如下:
Apr 2013 3000 Toys
Feb 2013 50000 Bicycle
Jan 2014 4546 Bananas
有什么简单的方法吗?
为什么不直接使用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;
看看本教程的例子6)> https://www.postgresqltutorial.com/postgresql-group-by/
您需要在GROUP BY上调用该函数,而不是调用在select上创建的虚拟属性的名称。
我正在做上面推荐的所有答案,我得到了一个“year_month”列不存在错误。
对我有用的是:
SELECT
date_trunc('month', created_at), 'MM/YYYY' AS month
FROM
"orders"
GROUP BY
date_trunc('month', created_at)
Postgres有几种时间戳类型:
不带时区的时间戳-(最好存储UTC时间戳)您可以在多国数据库存储中找到它。在本例中,客户端将负责每个国家的时区偏移。
timestamp with timezone -时区偏移量已经包含在时间戳中。
在某些情况下,您的数据库不使用时区,但您仍然需要根据本地时区和日光节约时间(例如https://www.timeanddate.com/time/zone/romania/bucharest)对记录进行分组。
要添加时区,您可以使用此示例并将时区偏移量替换为您的。
"your_date_column" at time zone '+03'
要添加特定于DST的+1夏季时间偏移量,您需要检查您的时间戳是否属于夏季夏令时。由于这些间隔以1天或2天为单位变化,我将使用一个不影响月末记录的近似值,因此在这种情况下,我可以忽略每年的确切间隔。
如果需要构建更精确的查询,则必须添加条件以创建更多的用例。但粗略地说,当你在数据库中发现没有时区的时间戳时,这将很好地按照时区和SummerTime每月分割数据:
SELECT
"id", "Product", "Sale",
date_trunc('month',
CASE WHEN
Extract(month from t."date") > 03 AND
Extract(day from t."date") > 26 AND
Extract(hour from t."date") > 3 AND
Extract(month from t."date") < 10 AND
Extract(day from t."date") < 29 AND
Extract(hour from t."date") < 4
THEN
t."date" at time zone '+03' -- Romania TimeZone offset + DST
ELSE
t."date" at time zone '+02' -- Romania TimeZone offset
END) as "date"
FROM
public."Table" AS t
WHERE 1=1
AND t."date" >= '01/07/2015 00:00:00'::TIMESTAMP WITHOUT TIME ZONE
AND t."date" < '01/07/2017 00:00:00'::TIMESTAMP WITHOUT TIME ZONE
GROUP BY date_trunc('month',
CASE WHEN
Extract(month from t."date") > 03 AND
Extract(day from t."date") > 26 AND
Extract(hour from t."date") > 3 AND
Extract(month from t."date") < 10 AND
Extract(day from t."date") < 29 AND
Extract(hour from t."date") < 4
THEN
t."date" at time zone '+03' -- Romania TimeZone offset + DST
ELSE
t."date" at time zone '+02' -- Romania TimeZone offset
END)
select to_char(date,'Mon') as mon,
extract(year from date) as yyyy,
sum("Sales") as "Sales"
from yourtable
group by 1,2
应Radu的要求,我将解释这一疑问:
to_char(date,'Mon') as Mon,:将"date"属性转换为定义的month的缩写形式。
extract(year from date) as yyyy: Postgresql的"extract"函数用于从"date"属性中提取yyyy年份。
sum("Sales")作为"Sales": sum()函数将所有"Sales"值相加,并提供区分大小写的别名,使用双引号保持大小写敏感。
group by 1,2: group by函数必须包含SELECT列表中不属于聚合的所有列(也就是SUM/AVG/MIN/MAX等函数中不包含的所有列)。这告诉查询,SUM()应该应用于列的每个唯一组合,在本例中是月列和年列。“1,2”部分是一种速记,而不是使用列别名,不过为了可读性,可能最好使用完整的“to_char(…)”和“extract(…)”表达式。