Mysql
 sql >> Datenbank >  >> RDS >> Mysql

Identifizieren von Benutzern mit einem Abwärtstrend SQL

Dies ist ein bisschen schwierig, und um Ergebnisse zu finden, die stetig ansteigen oder abfallen, sollten Sie wahrscheinlich die MATCH_RECOGNIZE -Klausel, die MySQL (noch) nicht unterstützt. Auf diese Weise können Sie ein Muster definieren, bei dem jede Menge kleiner als der vorherige Wert ist. Außerdem könnten Sie dies wahrscheinlich mit einem rekursiven cte tun, aber das würde außerhalb meiner Fähigkeiten liegen.

Hier ist, was ich mir ausgedacht habe, mit der Einschränkung, dass es nur den ersten und den letzten Wert vergleicht:

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)

Was ergibt:

CUSTOMER
Bob
Mary

Oder, um mit einem bekannten Maximum strikt abzunehmen, können Sie sie alle miteinander verketten, was ziemlich hässlich wird:

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

Was ergibt:

CUSTOMER
Mary

Aber für einen unbekannten Betrag würde ich match_recognize denken wäre die beste Lösung (oder Sie könnten eine Rekursion oder eine benutzerdefinierte Funktion hinzufügen).