PostgreSQL:根据步骤(日、月、年)计算期间的列值总和
PosrgteSQL: the sum of the column values for the period depending on the step (day, month, year)
我想创建一个存储过程或函数,returns 根据步骤(日、月、年)计算期间列值的总和。例如,我有 table 消费数据。它每 15 分钟保存一次数据。我想获得 2019-05-01 至 2019-05-10 期间的报告,步骤为“1 天”。我需要为这个时间间隔内的每一天定义一个每日数据集,并获取每一天的值的总和。
然后程序returns数据到Laravel。基于此数据图表构建。
我现在的代码:
CREATE OR REPLACE FUNCTION "public"."test"("meterid" int4, "started" text, "ended" text, "preiod" text)
RETURNS TABLE("_kwh" numeric, "datetime" timestamp) AS $BODY$BEGIN
RETURN QUERY
SELECT kwh, a_datetime
FROM "public"."consumption"
WHERE meter_id = meterid
AND a_datetime
BETWEEN to_timestamp(started, 'YYYY-MM-DD HH24:MI:SS')
AND to_timestamp(ended, 'YYYY-MM-DD HH24:MI:SS');
END$BODY$
LANGUAGE plpgsql VOLATILE
COST 100
ROWS 1000
我正在使用 PostgreSQL 10.7。
您可以使用pg_generate_series(start, end, interval)
更多信息见:set returning functions
为了模拟您的情况,我创建了一个简单的 table:
postgres=# create table consumption (kwh int, datetime date);
CREATE TABLE
postgres=# insert into consumption values (10, 2019-01-01);
ERROR: column "datetime" is of type date but expression is of type integer
postgres=# insert into consumption values (10, '2019-01-01');
INSERT 0 1
postgres=# insert into consumption values (2, '2019-01-03');
INSERT 0 1
postgres=# insert into consumption values (24, '2019-03-06');
INSERT 0 1
postgres=# insert into consumption values (30, '2019-03-22');
INSERT 0 1
并用 generate_series()
制作了 select
postgres=# SELECT COALESCE(SUM(kwh), 0) AS kwh,
period::DATE
FROM GENERATE_SERIES('2019-01-01','2019-12-31', '1 day'::interval) AS period
LEFT JOIN consumption ON period::DATE=datetime::DATE
GROUP BY 2
kwh | period
-----+------------
0 | 2019-04-17
0 | 2019-05-29
....
0 | 2019-04-06
0 | 2019-04-26
2 | 2019-01-03
0 | 2019-03-15
...
0 | 2019-11-21
0 | 2019-07-24
30 | 2019-03-22
0 | 2019-05-22
0 | 2019-11-19
...
我想创建一个存储过程或函数,returns 根据步骤(日、月、年)计算期间列值的总和。例如,我有 table 消费数据。它每 15 分钟保存一次数据。我想获得 2019-05-01 至 2019-05-10 期间的报告,步骤为“1 天”。我需要为这个时间间隔内的每一天定义一个每日数据集,并获取每一天的值的总和。
然后程序returns数据到Laravel。基于此数据图表构建。
我现在的代码:
CREATE OR REPLACE FUNCTION "public"."test"("meterid" int4, "started" text, "ended" text, "preiod" text)
RETURNS TABLE("_kwh" numeric, "datetime" timestamp) AS $BODY$BEGIN
RETURN QUERY
SELECT kwh, a_datetime
FROM "public"."consumption"
WHERE meter_id = meterid
AND a_datetime
BETWEEN to_timestamp(started, 'YYYY-MM-DD HH24:MI:SS')
AND to_timestamp(ended, 'YYYY-MM-DD HH24:MI:SS');
END$BODY$
LANGUAGE plpgsql VOLATILE
COST 100
ROWS 1000
我正在使用 PostgreSQL 10.7。
您可以使用pg_generate_series(start, end, interval)
更多信息见:set returning functions
为了模拟您的情况,我创建了一个简单的 table:
postgres=# create table consumption (kwh int, datetime date);
CREATE TABLE
postgres=# insert into consumption values (10, 2019-01-01);
ERROR: column "datetime" is of type date but expression is of type integer
postgres=# insert into consumption values (10, '2019-01-01');
INSERT 0 1
postgres=# insert into consumption values (2, '2019-01-03');
INSERT 0 1
postgres=# insert into consumption values (24, '2019-03-06');
INSERT 0 1
postgres=# insert into consumption values (30, '2019-03-22');
INSERT 0 1
并用 generate_series()
postgres=# SELECT COALESCE(SUM(kwh), 0) AS kwh,
period::DATE
FROM GENERATE_SERIES('2019-01-01','2019-12-31', '1 day'::interval) AS period
LEFT JOIN consumption ON period::DATE=datetime::DATE
GROUP BY 2
kwh | period
-----+------------
0 | 2019-04-17
0 | 2019-05-29
....
0 | 2019-04-06
0 | 2019-04-26
2 | 2019-01-03
0 | 2019-03-15
...
0 | 2019-11-21
0 | 2019-07-24
30 | 2019-03-22
0 | 2019-05-22
0 | 2019-11-19
...