[SQL] zliczanie ilości rekordów z warunkiem

0

Cześć,
Zmóżdżam się nad takim oto zadaniem. Mam tabelkę (stany):

DATA TOWAR STAN1 STAN2 RÓŻNICA
2020-01-01 towar1 10 9 1
2020-01-02 towar1 11 9 2
2020-01-03 towar1 15 14 1
2020-01-04 towar1 12 12 0
2020-01-05 towar1 10 10 0
2020-01-06 towar1 10 8 2
2020-01-07 towar1 5 5 0
2020-01-08 towar1 4 4 0
2020-01-09 towar1 3 3 0
2020-01-10 towar1 1 1 0

Chodzi o zliczenie od jak dawna różnica między polami STAN1 i STAN2 utrzymuje się na niezmienionym poziomie. W powyższym przypadku wynik zapytania puszczonego na dzień 2020-01-07 powinno zwrócić 4 (od 4 dni różnica wynosi 0).
Próbowałem coś w tym stylu:

SELECT t.*,
       row_number() over(PARTITION BY towar, roznica ORDER BY data ASC) AS dni
  FROM stany t
 ORDER BY 1;

ale wynik nie jest poprawny, gdyż nie zlicza on nieprzerwanych ciągów (dzień po dniu). Ktoś ma jakiś pomysł?

0

Hmm, trochę nie do końca poprawnie. Zapytanie pomija wpisy gdzie różnica zmienia się codziennie.

W ogóle docelowo chciałbym pokazać takie towary, dla których różnica, którą mamy dziś, utrzymuje się powiedzmy od minimum 3 dni na niezmienionym poziomie.
Czyli w tym przypadku:
https://dbfiddle.uk/?rdbms=postgres_12&fiddle=53040009db75f7b1682bbb90b3c5db17
przyjmując, że mamy dziś 10 stycznia w wyniku powinienem otrzymać: towar1 - różnica 0 od 4 dni, towar2 - różnica 2 od 2 dni, towar3 - różnica 1 od 1 dnia.

Dopiszę może bardzej obrazowo o co chodzi :)
Mam bazę produktów wraz z informacją o ilości w systemie magazynowym. Do tego z drugiej strony mam bazę tych produktów w innym systemie. Chodzi mi o to, żeby wyłapywać i poddawać analizie ruchy na produktach, które mają różne stany ilościowe w obu systemach, ale ponieważ specyfikę mam taką jaką mam, zakładam, że mogą być małe (2-3 dniowe) opóźnienia to chcę wyłapywać tylko te produkty, dla których mam różnicę na niezmienionym poziomie (różnym od 0) od np 5 dni.

1

Może taki potworek? Trick polega na tym, że różnica DATE_PART('day', AGE(data, '1970-01-01')) - ROW_NUMBER() będzie stała dla dni które następują po sobie.

SELECT 
    towar, 
    różnica, 
    MIN(data) AS start_date, 
    MAX(data) AS end_date,
    AGE(MAX(data), MIN(data)) as length
FROM (
    SELECT
        data, 
        towar, 
        różnica,
        DATE_PART('day', AGE(data, '1970-01-01')) - ROW_NUMBER() OVER(PARTITION BY towar, różnica ORDER BY data) AS period_id
    FROM (
        SELECT DISTINCT 
            data,
            towar,
            różnica 
        FROM x
    ) as temp_1
) as temp_2
GROUP BY towar, różnica, period_id
ORDER BY towar, MIN(data);

Test na Postgres 12: https://dbfiddle.uk/?rdbms=postgres_12&fiddle=af705d853b99351829bffbd08ae3309e

1 użytkowników online, w tym zalogowanych: 0, gości: 1