sql >> Databasteknik >  >> RDS >> PostgreSQL

Generera tidsserier med daglig statistik med hjälp av en PostgreSQL-fråga

Steg 1. Beräkna en kumulativ summa av tillstånd för varje order, med värdena NY =1, AKTIV =1, KLAR =2:

select 
    order_id, timestamp::date as day, 
    sum(case new_state when 'DONE' then 2 else 1 end) over w as state
from order_state_history h
join orders o on o.id = h.order_id
where o.type = 1
window w as (partition by order_id order by timestamp)

 order_id |    day     | state 
----------+------------+-------
    10000 | 2001-01-01 |     1
    10000 | 2001-01-02 |     2
    10000 | 2001-01-03 |     4
    10001 | 2001-01-02 |     1
    10004 | 2001-01-05 |     1
    10004 | 2001-01-10 |     3
(6 rows)

Steg 2. Beräkna en övergångsmatris för varje order baserat på tillstånd från steg 1 (2 betyder NY->AKTIV, 3 betyder NY->KLAR, 4 betyder AKTIV->KLAR):

select 
    order_id, day, state,
    case when state = 1 then 1 when state = 2 or state = 3 then -1 else 0 end as new,
    case when state = 2 then 1 when state = 4 then -1 else 0 end as active,
    case when state > 2 then 1 else 0 end as done
from (
    select 
        order_id, timestamp::date as day, 
        sum(case new_state when 'DONE' then 2 else 1 end) over w as state
    from order_state_history h
    join orders o on o.id = h.order_id
    where o.type = 1
    window w as (partition by order_id order by timestamp)
    ) s

 order_id |    day     | state | new | active | done 
----------+------------+-------+-----+--------+------
    10000 | 2001-01-01 |     1 |   1 |      0 |    0
    10000 | 2001-01-02 |     2 |  -1 |      1 |    0
    10000 | 2001-01-03 |     4 |   0 |     -1 |    1
    10001 | 2001-01-02 |     1 |   1 |      0 |    0
    10004 | 2001-01-05 |     1 |   1 |      0 |    0
    10004 | 2001-01-10 |     3 |  -1 |      0 |    1
(6 rows)

Steg 3. Beräkna en kumulativ summa av varje tillstånd för en serie dagar:

select distinct
    day::date,
    sum(new) over w as new,
    sum(active) over w as active,
    sum(done) over w as done
from generate_series('2001-01-01'::date, '2001-01-10', '1d'::interval) day
left join (
    select 
        order_id, day, state,
        case when state = 1 then 1 when state = 2 or state = 3 then -1 else 0 end as new,
        case when state = 2 then 1 when state = 4 then -1 else 0 end as active,
        case when state > 2 then 1 else 0 end as done
    from (
        select 
            order_id, timestamp::date as day, 
            sum(case new_state when 'DONE' then 2 else 1 end) over w as state
        from order_state_history h
        join orders o on o.id = h.order_id
        where o.type = 1
        window w as (partition by order_id order by timestamp)
        ) s
    ) s
using(day)
window w as (order by day)
order by 1

    day     | new | active | done 
------------+-----+--------+------
 2001-01-01 |   1 |      0 |    0
 2001-01-02 |   1 |      1 |    0
 2001-01-03 |   1 |      0 |    1
 2001-01-04 |   1 |      0 |    1
 2001-01-05 |   2 |      0 |    1
 2001-01-06 |   2 |      0 |    1
 2001-01-07 |   2 |      0 |    1
 2001-01-08 |   2 |      0 |    1
 2001-01-09 |   2 |      0 |    1
 2001-01-10 |   1 |      0 |    2
(10 rows)   



  1. Hur man duplicerar scheman i PostgreSQL

  2. Laravel-migrering - Överträdelse av integritetsbegränsning:1452 Kan inte lägga till eller uppdatera en underordnad rad:en främmande nyckel-begränsning misslyckas

  3. Stänga av och starta Oracle-instansen

  4. konvertera php date till mysql-format