sql >> Databasteknik >  >> RDS >> Mysql

Identifiera användare med en nedåtgående SQL-trend

Det här är lite knepigt, och för att hitta resultat som stadigt ökar eller minskar skulle du förmodligen vilja använda MATCH_RECOGNIZE klausul, som MySQL (ännu) inte stöder. På så sätt kan du definiera ett mönster där varje kvantitet är mindre än det föregående värdet. Dessutom skulle du förmodligen kunna göra detta med en rekursiv cte, men det skulle ligga utanför mina förmågor.

Här är vad jag kom fram till, med varningen att den bara jämför de första och sista värdena:

WITH
    tbl (customer, purchasedate, quantity) AS (
SELECT * FROM VALUES 
    ('Bob',         '9/1/2021',        10),
    ('Bob',         '9/10/2021',       6),
    ('Bob',         '9/18/2021',       5),
    ('Bob',         '9/19/2021',       8),
    ('Mary',        '9/1/2021',        10),
    ('Mary',        '9/10/2021',       6),
    ('Mary',        '9/18/2021',       5),
    ('Mary',        '9/19/2021',       3),
    ('Frank',       '9/1/2021',        5),
    ('Lucus',       '9/1/2021',        5),
    ('Lucus',       '9/10/2021',       6),
    ('Lucus',       '9/18/2021',       10)
)

SELECT
    DISTINCT customer
FROM
    tbl
QUALIFY
      FIRST_VALUE(quantity) OVER (partition BY customer ORDER BY purchasedate)
    > LAST_VALUE(quantity)  OVER (PARTITION BY customer ORDER BY purchasedate)

Vilket ger:

CUSTOMER
Bob
Mary

Eller, för att få strikt minskning med ett känt max, kan du koppla ihop dem alla, vilket blir ganska fult:

WITH
    tbl (customer, purchasedate, quantity) AS (
SELECT * FROM VALUES 
    ('Bob',         '9/1/2021',        10),
    ('Bob',         '9/10/2021',       6),
    ('Bob',         '9/18/2021',       5),
    ('Bob',         '9/19/2021',       8),
    ('Mary',        '9/1/2021',        10),
    ('Mary',        '9/10/2021',       6),
    ('Mary',        '9/18/2021',       5),
    ('Mary',        '9/19/2021',       3),
    ('Frank',       '9/1/2021',        5),
    ('Lucus',       '9/1/2021',        5),
    ('Lucus',       '9/10/2021',       6),
    ('Lucus',       '9/18/2021',       10)
)

SELECT
    DISTINCT customer
FROM
    tbl
    qualify 
        (NTH_VALUE(quantity, 1) OVER (partition BY customer ORDER BY purchasedate) >= NTH_VALUE(quantity, 2) OVER (partition BY customer ORDER BY purchasedate))
        and ((NTH_VALUE(quantity, 2) OVER (partition BY customer ORDER BY purchasedate) >= NTH_VALUE(quantity, 3) OVER (partition BY customer ORDER BY purchasedate)) or (NTH_VALUE(quantity, 3) OVER (partition BY customer ORDER BY purchasedate) is null))
        and ((NTH_VALUE(quantity,3) OVER (partition BY customer ORDER BY purchasedate) >= NTH_VALUE(quantity, 4) OVER (partition BY customer ORDER BY purchasedate)) or (NTH_VALUE(quantity, 4) OVER (partition BY customer ORDER BY purchasedate) is null))

Vilket ger:

CUSTOMER
Mary

Fast för ett okänt belopp skulle jag tro match_recognize skulle vara den bästa lösningen (eller så kan du lägga till någon rekursion eller en anpassad funktion).



  1. SQL, Vid radera kaskad och vid uppdateringskaskad

  2. Använd MySQL relationsdatabaser på Fedora 12

  3. inno db isoleringsnivåer och låsning

  4. Det går inte att köra dynamisk fråga i lagrad procedur när man väljer antal poster