PostgreSQL
 sql >> Baza danych >  >> RDS >> PostgreSQL

Funkcja warunkowego wyprzedzenia/opóźnienia PostgreSQL?

Twoja definicja:

zajęcia z grupy B odbywają się zawsze po zajęciach z grupy A.

.. logicznie oznacza, że ​​na użytkownika przypada 0 lub 1 aktywność B po 1 lub więcej aktywności A. Nigdy więcej niż 1 B czynności w kolejności.

Możesz sprawić, by działała z funkcją pojedynczego okna, DISTINCT ON i CASE , co powinno być najszybszym sposobem dla niewielu wierszy na użytkownika (patrz także poniżej):

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<>graj tutaj

SQL CASE domyślne wyrażenie to NULL jeśli nie ELSE gałąź została dodana, więc zachowałem to krótko.

Zakładając time jest zdefiniowany NOT NULL . W przeciwnym razie możesz dodać NULLS LAST . Dlaczego?

  • Sortować według kolumny ASC, ale najpierw wartości NULL?

(activity LIKE 'A%' OR activity LIKE 'B%') jest bardziej gadatliwy niż activity ~ '^[AB]' , ale zazwyczaj szybciej w starszych wersjach Postgresa. Informacje o dopasowywaniu wzorców:

  • Dopasowywanie wzorców za pomocą LIKE, SIMILAR TO lub wyrażeń regularnych w PostgreSQL

Warunkowe funkcje okna?

To właściwie możliwe . Możesz połączyć agregację FILTER klauzula z OVER klauzula funkcji okna. Jednak :

  1. FILTER sama klauzula może działać tylko z wartościami z bieżącego wiersza.

  2. Co ważniejsze, FILTER nie jest zaimplementowany dla czystych, oryginalnych funkcji, takich jak lead() lub lag() (do Postgres 13) - tylko dla funkcji agregujących.

Jeśli spróbujesz:

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

Postgres powie Ci:

FILTER is not implemented for non-aggregate window functions

O FILTER :

  • Agregacja kolumn z dodatkowymi (odrębnymi) filtrami
  • Odwoływanie się do bieżącego wiersza w klauzuli FILTER funkcji okna

Wydajność

Dla niewielu użytkownicy z niewieloma wierszy na użytkownika, prawie dowolny zapytanie jest szybkie, nawet bez indeksu.

Dla wielu użytkowników i niewielu wierszy na użytkownika, pierwsze zapytanie powyżej powinno być najszybsze. Zobacz:

  • Wybrać pierwszy wiersz w każdej grupie GROUP BY?

Dla wielu wierszy na użytkownika, jest (potencjalnie dużo ) szybsze techniki, w zależności od szczegółów konfiguracji. Zobacz:

  • Zoptymalizuj zapytanie GROUP BY, aby pobrać ostatni wiersz na użytkownika


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Jak uzyskać klucze podstawowe tabeli z Postgres za pośrednictwem plpgsql?

  2. Zapytanie o szerokość geograficzną PostgreSQL

  3. Robienie GDZIE W na wielu kolumnach w Postgresql

  4. Błąd podczas ustawiania n_distinct przy użyciu zmiennej plpgsql

  5. Jak zmienić typ kolumny w Heroku?