PostgreSQL
 sql >> Teknologi Basis Data >  >> RDS >> PostgreSQL

Lompat celah SQL pada kondisi tertentu &penggunaan lead() yang tepat

Kueri dengan fungsi jendela

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

Selain apa yang sudah kami miliki , kita membutuhkan tombol OFF yang valid.

Sebuah OFF beralih jika valid jika perangkat diaktifkan ON sebelumnya (last_status = 1 ) dan ON berikutnya operasi setelah itu datang setelah OFF alihkan pertanyaan (next_id_of_last_status > id ).

Kami harus menyediakan kasus khusus yang ada ON terakhir operasi, jadi kami memeriksa NULL sebagai tambahan (OR next_id_of_last_status IS NULL ).

next_id_of_last_status berasal dari jendela yang sama dengan yang kita ambil last_status dari. Oleh karena itu saya memperkenalkan sintaks tambahan untuk deklarasi jendela eksplisit, jadi saya tidak perlu mengulang sendiri:

WINDOW w2 AS (PARTITION BY val ORDER BY id)

Dan kita perlu mendapatkan id selanjutnya untuk status terakhir di subquery tadi (subquery t ).

Jika Anda telah memahami semua itu , Anda tidak akan kesulitan menampar lead() di atas kueri ini untuk mencapai tujuan akhir Anda. :)

Fungsi PL/pgSQL

Setelah menjadi kompleks ini, saatnya beralih ke pemrosesan prosedural.

fungsi plpgsql yang relatif sederhana ini menghentikan kinerja kueri fungsi jendela yang kompleks, karena alasan sederhana bahwa ia harus memindai seluruh tabel hanya sekali.

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$;

Telepon:

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. Nilai SQL dari tanggal sebelumnya (tidak diketahui)

  2. Cara mengatur skema default di Yii2

  3. PHP dan Postgres:menangkap kesalahan?

  4. Tidak dapat memulai postgresql.service?

  5. Oracle ke PostgreSQL — Kursor dan pohon