PostgreSQL
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> PostgreSQL

Nhảy khoảng cách SQL qua điều kiện cụ thể và sử dụng chì () thích hợp

Truy vấn với các hàm cửa sổ

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

Ngoài những gì chúng tôi đã có , chúng tôi cần các công tắc TẮT hợp lệ.

OFF chuyển nếu hợp lệ nếu thiết bị đã được chuyển ON trước (last_status = 1 ) và ON tiếp theo hoạt động sau đó đến sau OFF chuyển câu hỏi (next_id_of_last_status > id ).

Chúng tôi phải cung cấp cho trường hợp đặc biệt rằng có ON cuối cùng hoạt động, vì vậy chúng tôi kiểm tra NULL ngoài ra (OR next_id_of_last_status IS NULL ).

next_id_of_last_status đến từ cùng một cửa sổ mà chúng tôi lấy last_status từ. Do đó, tôi đã giới thiệu cú pháp bổ sung cho khai báo cửa sổ rõ ràng, vì vậy tôi không phải lặp lại chính mình:

WINDOW w2 AS (PARTITION BY val ORDER BY id)

Và chúng ta cần lấy id tiếp theo cho trạng thái cuối cùng trong truy vấn con trước đó (truy vấn con t ).

Nếu bạn đã hiểu tất cả điều đó , bạn sẽ không gặp sự cố khi tát lead() trên đầu trang của truy vấn này để đến điểm đến cuối cùng của bạn. :)

Hàm PL / pgSQL

Khi nó trở nên phức tạp, đã đến lúc chuyển sang xử lý theo thủ tục.

Hàm plpgsql tương đối đơn giản này làm ảnh hưởng đến hiệu suất của truy vấn hàm cửa sổ phức tạp, vì lý do đơn giản là nó chỉ phải quét toàn bộ bảng một lần.

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

Gọi:

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. Cách POSITION () hoạt động trong PostgreSQL

  2. Lấy từ cuối cùng từ một chuỗi Postgres, một cách khai báo

  3. Ngăn chặn gốc của danh từ riêng trong PostgreSQL?

  4. dữ liệu mùa xuân jpa còn lại không cần thiết

  5. Thay thế chuỗi con PostgreSQL UPDATE