sql >> Databáze >  >> RDS >> PostgreSQL

Funkce podmíněného vedení/zpoždění PostgreSQL?

Vaše definice:

aktivita ze skupiny B probíhá vždy po aktivitě ze skupiny A.

.. logicky znamená, že na uživatele připadá 0 nebo 1 aktivita B po 1 nebo více aktivitách A. Nikdy více než 1 B aktivity za sebou.

Můžete to zprovoznit pomocí funkce jednoho okna, DISTINCT ON a CASE , což by měl být nejrychlejší způsob pro málo řádků na uživatele (viz také níže):

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<>zde hrajte

CASE SQL výchozí hodnota výrazu je NULL pokud není ELSE větev je přidána, takže jsem to zkrátil.

Za předpokladu time je definováno NOT NULL . Jinak možná budete chtít přidat NULLS LAST . Proč?

  • Seřadit podle sloupce ASC, ale nejprve hodnoty NULL?

(activity LIKE 'A%' OR activity LIKE 'B%') je podrobnější než activity ~ '^[AB]' , ale obvykle rychlejší ve starších verzích Postgres. O shodě vzorů:

  • Shoda vzoru s LIKE, SIMILAR TO nebo regulárními výrazy v PostgreSQL

Podmíněné funkce okna?

To je vlastně možné . Souhrnný FILTER můžete kombinovat klauzule s OVER klauzule okenních funkcí. Nicméně :

  1. FILTER samotná klauzule může pracovat pouze s hodnotami z aktuálního řádku.

  2. A co je důležitější, FILTER není implementován pro čistě originální funkce jako lead() nebo lag() (až do Postgres 13) – pouze pro agregační funkce.

Pokud to zkusíte:

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

Postgres vám řekne:

FILTER is not implemented for non-aggregate window functions

O FILTER :

  • Agregujte sloupce pomocí dalších (odlišných) filtrů
  • Odkaz na aktuální řádek v klauzuli FILTER funkce okna

Výkon

Pro málo uživatelé s málo řádků na uživatele, v podstatě libovolné dotaz je rychlý, i bez indexu.

Pro mnoho uživatelů a několika řádků na uživatele, první výše uvedený dotaz by měl být nejrychlejší. Viz:

  • Vybrat první řádek v každé skupině GROUP BY?

Pro mnoho řádků na uživatele, existuje (potenciálně hodně ) rychlejší techniky, v závislosti na podrobnostech vašeho nastavení. Viz:

  • Optimalizujte dotaz GROUP BY pro načtení posledního řádku na uživatele


  1. Rozdělte varchar do samostatných sloupců v Oracle

  2. PŘIPOJIT SE k MySQL vs POUŽÍVAT?

  3. Pandy zapisují datový rámec do jiného schématu postgresql

  4. Špatný pohotovostní režim