sql >> Database teknologi >  >> RDS >> PostgreSQL

Betinget lead/lag funktion PostgreSQL?

Din definition:

aktivitet fra gruppe B foregår altid efter aktivitet fra gruppe A.

.. indebærer logisk, at der pr. bruger er 0 eller 1 B-aktivitet efter 1 eller flere A-aktiviteter. Aldrig mere end 1 B aktiviteter i rækkefølge.

Du kan få det til at fungere med en enkelt vinduesfunktion, DISTINCT ON og CASE , hvilket burde være den hurtigste måde for rækker pr. bruger (se også nedenfor):

SELECT name
     , CASE WHEN a2 LIKE 'B%' THEN a1 ELSE a2 END AS activity
     , CASE WHEN a2 LIKE 'B%' THEN a2 END AS next_activity
FROM  (
   SELECT DISTINCT ON (name)
          name
        , lead(activity) OVER (PARTITION BY name ORDER BY time DESC) AS a1
        , activity AS a2
   FROM   t
   WHERE (activity LIKE 'A%' OR activity LIKE 'B%')
   ORDER  BY name, time DESC
   ) sub;

db<>spil her

En SQL CASE udtryk er standard til NULL hvis ingen ELSE gren er tilføjet, så jeg holdt det kort.

Forudsat time er defineret NOT NULL . Ellers vil du måske tilføje NULLS LAST . Hvorfor?

  • Sortere efter kolonne ASC, men NULL-værdier først?

(activity LIKE 'A%' OR activity LIKE 'B%') er mere omfattende end activity ~ '^[AB]' , men typisk hurtigere i ældre versioner af Postgres. Om mønstermatchning:

  • Mønstermatching med LIKE, SIMILAR TO eller regulære udtryk i PostgreSQL

Betingede vinduesfunktioner?

Det er faktisk muligt . Du kan kombinere det samlede FILTER klausul med OVER klausul af vinduesfunktioner. Men :

  1. FILTER selve klausulen kan kun fungere med værdier fra den aktuelle række.

  2. Endnu vigtigere, FILTER er ikke implementeret for rene ægte funktioner som lead() eller lag() (op til Postgres 13) - kun for aggregerede funktioner.

Hvis du prøver:

lead(activity) FILTER (WHERE activity LIKE 'A%') OVER () AS activity

Postgres vil fortælle dig:

FILTER is not implemented for non-aggregate window functions

Om FILTER :

  • Samlet kolonner med yderligere (særskilte) filtre
  • Referencer til den aktuelle række i FILTER-sætningen af ​​vinduesfunktionen

Ydeevne

For brugere med rækker pr. bruger, stort set alle forespørgslen er hurtig, selv uden indeks.

For mange brugere og rækker pr. bruger, bør den første forespørgsel ovenfor være hurtigst. Se:

  • Vælg første række i hver GROUP BY-gruppe?

For mange rækker pr. bruger, der er (potentielt meget ) hurtigere teknikker, afhængigt af detaljerne i din opsætning. Se:

  • Optimer GROUP BY-forespørgsel for at hente seneste række pr. bruger


  1. Sådan opretter du en database i MySQL Workbench ved hjælp af GUI

  2. Hvordan læser og opdaterer jeg SQLite-database ved hjælp af ListView i Android?

  3. Sådan begrænser du resultater i T-SQL

  4. SQL Server - Forespørgsel kortslutning?