PostgreSQL
 sql >> база данни >  >> RDS >> PostgreSQL

Прескачане на пропуск в SQL при специфично условие и правилно използване на lead().

Заявка с прозоречни функции

SELECT *
FROM  (
   SELECT *
         ,lag(val, 1, 0)    OVER (PARTITION BY status ORDER BY id) AS last_val
         ,lag(status, 1, 0) OVER w2 AS last_status
         ,lag(next_id)      OVER w2 AS next_id_of_last_status
   FROM  (
      SELECT *, lead(id) OVER (PARTITION BY status ORDER BY id) AS next_id
      FROM   t1
      ) AS t
   WINDOW w2 AS (PARTITION BY val ORDER BY id)
  ) x
WHERE (last_val <> val OR last_status <> status)
AND   (status = 1 
       OR last_status = 1
          AND ((next_id_of_last_status > id) OR next_id_of_last_status IS NULL)
      )
ORDER  BY id

В допълнение към това, което вече имахме , имаме нужда от валидни превключватели за ИЗКЛ.

OFF превключвател, ако е валиден, ако устройството е било включено ON преди (last_status = 1 ) и следващия ON операция след това идва след OFF въпросният превключвател (next_id_of_last_status > id ).

Трябва да предвидим специалния случай, че е последното ON операция, така че проверяваме за NULL в допълнение (OR next_id_of_last_status IS NULL ).

next_id_of_last_status идва от същия прозорец, който вземаме last_status от. Затова въведох допълнителен синтаксис за изрична декларация на прозорец, така че не е нужно да се повтарям:

WINDOW w2 AS (PARTITION BY val ORDER BY id)

И трябва да получим следващия идентификатор за последния статус в подзаявка по-рано (подзаявка t ).

Ако сте разбрали всичко това , не би трябвало да имате проблем с пляскането на lead() върху тази заявка, за да стигнете до крайната си дестинация. :)

PL/pgSQL функция

След като стане толкова сложно, е време да преминете към процедурна обработка.

Тази сравнително проста plpgsql функция намалява производителността на сложната заявка за функцията на прозореца поради простата причина, че тя трябва да сканира цялата таблица само веднъж.

CREATE OR REPLACE FUNCTION valid_t1 (OUT t t1)  -- row variable of table type
  RETURNS SETOF t1 LANGUAGE plpgsql AS
$func$
DECLARE
   _last_on int := -1;  -- init with impossible value
BEGIN

FOR t IN
   SELECT * FROM t1 ORDER BY id
LOOP
   IF t.status = 1 THEN
      IF _last_on <> t.val THEN
         RETURN NEXT;
         _last_on := t.val;
      END IF;
   ELSE
      IF _last_on = t.val THEN
         RETURN NEXT;
         _last_on := -1;
      END IF;
   END IF;
END LOOP;

END
$func$;

Обаждане:

SELECT * FROM valid_t1();



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Как заобикаляте ограничението на размера на Docker.qcow2 в Docker за Mac?

  2. Как да предотвратите „невалиден входен синтаксис за тип json“ в Postgres, когато записите съдържат комбинация от json или низове

  3. Как да не се показва парола в ясен текст при свързване към postgres чрез sqlalchemy, psycopg2?

  4. Как Asin() работи в PostgreSQL

  5. Преглед на генерираните колони за PostgreSQL