sql >> Database >  >> RDS >> PostgreSQL

Voorwaardelijke lead/lag-functie PostgreSQL?

Jouw definitie:

activiteit uit groep B vindt altijd plaats na activiteit uit groep A.

.. houdt logisch in dat er per gebruiker 0 of 1 B-activiteit is na 1 of meer A-activiteiten. Nooit meer dan 1 B-activiteiten achter elkaar.

Je kunt het laten werken met een enkele vensterfunctie, DISTINCT ON en CASE , wat de snelste manier zou moeten zijn voor weinigen rijen per gebruiker (zie ook hieronder):

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<>viool hier

Een SQL CASE uitdrukking is standaard NULL indien geen ELSE branch is toegevoegd, dus dat heb ik kort gehouden.

Uitgaande van time is gedefinieerd NOT NULL . Anders wilt u misschien NULLS LAST . toevoegen . Waarom?

  • Sorteren op kolom ASC, maar NULL-waarden eerst?

(activity LIKE 'A%' OR activity LIKE 'B%') is uitgebreider dan activity ~ '^[AB]' , maar doorgaans sneller in oudere versies van Postgres. Over patroonherkenning:

  • Patroon komt overeen met LIKE, VERGELIJKBAAR MET of reguliere expressies in PostgreSQL

Voorwaardelijke vensterfuncties?

Dat is eigenlijk mogelijk . U kunt het geaggregeerde FILTER . combineren clausule met de OVER clausule van vensterfuncties. Echter :

  1. De FILTER clausule zelf kan alleen werken met waarden uit de huidige rij.

  2. Wat nog belangrijker is, FILTER is niet geïmplementeerd voor pure echte functies zoals lead() of lag() (tot Postgres 13) - alleen voor geaggregeerde functies.

Als je het probeert:

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

Postgres zal je vertellen:

FILTER is not implemented for non-aggregate window functions

Over FILTER :

  • Samengevoegde kolommen met extra (verschillende) filters
  • Verwijzen naar huidige rij in FILTER-clausule van vensterfunctie

Prestaties

Voor enkele gebruikers met weinig rijen per gebruiker, vrijwel elke zoekopdracht is snel, zelfs zonder index.

Voor velen gebruikers en weinig rijen per gebruiker, moet de eerste zoekopdracht hierboven het snelst zijn. Zie:

  • Selecteer de eerste rij in elke GROUP BY-groep?

Voor velen rijen per gebruiker zijn er (mogelijk veel ) snellere technieken, afhankelijk van de details van uw opstelling. Zie:

  • Optimaliseer de GROUP BY-query om de laatste rij per gebruiker op te halen


  1. Hoe u alle tabellen in Oracle kunt weergeven

  2. .NET / Oracle:een script met DDL-instructies programmatisch uitvoeren

  3. Java:een opgeslagen procedure aanroepen in een Oracle-database

  4. Hoe gebruik ik Timestamp_to_scn en Scn_to_timestamp in Oracle?