sql >> Databasteknik >  >> RDS >> PostgreSQL

Summa tills tröskelvärdet nås och nollställ sedan räknaren

Använd användardefinierat aggregat

Livetest:http://sqlfiddle.com/#!17/16716/2

SELECT *, sum_with_reset(distance, 10) over (order by date asc) as running_distance 
FROM tbl;

Användardefinierad aggregerad summa_med_återställningsdefinition:

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
);

Data

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)
;

Utdata:

| 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 |

One-liner:

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 boolean kan casta sant till 1, false till 0 genom att använda castoperatorn ::int .

Du kan använda plpgsql språk också:

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';

Observera att du inte kan skapa plpgsql-funktionen på sqlfiddle.com, så du kan inte testa den plpgsql-koden på sqlfiddle.com. Det kan du dock på din maskin.



  1. PostgreSQL-motsvarighet för SQL Server GROUP BY WITH ROLLUP

  2. Postgresql-fråga för att få n-nivå förälder-barn-relation lagrad i en enda tabell

  3. PostgreSQL VALUES Kommando förklaras

  4. MySQL - Behövs INTE NULL-begränsningar för primärnycklar?