user_id | date | distance 1 | 2019-04-09 00:00:00 | 2 1 | 2019-04-09 00:00:30 | 5 1 | 2019-04-09 00:01:00 | 3 1 | 2019-04-09 00:01:45 | 7 1 | 2019-04-09 00:02:30 | 6 1 | 2019-04-09 00:03:00 | 1
如何求和下一行的总和,直到达到阈值点,然后再次重置计数器。
例如,如果阈值是10,我试图获得以下输出:
1 | 2019-04-09 00:00:00 | 2 1 | 2019-04-09 00:00:30 | 7 (2 + 5) 1 | 2019-04-09 00:01:00 | 10 ( 7 + 3 ) 1 | 2019-04-09 00:01:45 | 7 RESET 1 | 2019-04-09 00:02:30 | 13 (7 + 6 ) 1 | 2019-04-09 00:03:00 | 1 RESET
但是我只能通过以下查询获得累计距离:
SELECT *, sum(distance) over (order by date asc) as running_distance FROM table;
我正在使用PostgreSQL。
使用用户定义的聚合
实时测试:http://sqlfiddle.com/#!17/16716/2
SELECT *, sum_with_reset(distance, 10) over (order by date asc) as running_distance FROM tbl;
用户定义的合计sum_with_reset定义:
create or replace function sum_reset_accum( _accumulated numeric, _current numeric, _threshold numeric ) returns numeric as $$ select case when _accumulated >= _threshold then _current else _current + _accumulated end $$ language sql; create aggregate sum_with_reset(numeric, numeric) ( sfunc = sum_reset_accum, stype = numeric, initcond = 0 );
数据
CREATE TABLE tbl ("user_id" int, "date" timestamp, "distance" int) ; INSERT INTO tbl ("user_id", "date", "distance") VALUES (1, '2019-04-09 00:00:00', 2), (1, '2019-04-09 00:00:30', 5), (1, '2019-04-09 00:01:00', 3), (1, '2019-04-09 00:01:45', 7), (1, '2019-04-09 00:02:30', 6), (1, '2019-04-09 00:03:00', 1) ;
输出:
| user_id | date | distance | running_distance | |---------|----------------------|----------|------------------| | 1 | 2019-04-09T00:00:00Z | 2 | 2 | | 1 | 2019-04-09T00:00:30Z | 5 | 7 | | 1 | 2019-04-09T00:01:00Z | 3 | 10 | | 1 | 2019-04-09T00:01:45Z | 7 | 7 | | 1 | 2019-04-09T00:02:30Z | 6 | 13 | | 1 | 2019-04-09T00:03:00Z | 1 | 1 |
单线:
create or replace function sum_reset_accum( _accumulated numeric, _current numeric, _threshold numeric ) returns numeric as $$ select _current + _accumulated * (_accumulated < _threshold)::int $$ language 'sql';
Postgres布尔值可以使用cast操作符将true转换为1,将false转换为0 ::int。
::int
您也可以使用plpgsql语言:
plpgsql
create or replace function sum_reset_accum( _accumulated numeric, _current numeric, _threshold numeric ) returns numeric as $$begin return _current + _accumulated * (_accumulated < _threshold)::int; end$$ language 'plpgsql';
请注意,您无法在sqlfiddle.com上创建plpgsql函数,因此无法在sqlfiddle.com上测试该plpgsql代码。您可以,但是在您的机器上。