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

Kiểm tra xem NULL có tồn tại trong mảng Postgres không

Postgres 9.5 trở lên

Hoặc sử dụng array_position() . Về cơ bản:

SELECT array_position(arr, NULL) IS NOT NULL AS array_has_null

Xem bản trình diễn bên dưới.

Postgres 9.3 trở lên

Bạn có thể kiểm tra với các hàm tích hợp sẵn array_remove() hoặc array_replace() .

Postgres 9.1 hoặc bất kỳ phiên bản nào

Nếu bạn biết một phần tử duy nhất không bao giờ có thể tồn tại trong các mảng của bạn, bạn có thể sử dụng tính năng này nhanh biểu hiện. Giả sử, bạn có một mảng các số dương và -1 không bao giờ có thể ở trong đó:

-1 = ANY(arr) IS NULL

Câu trả lời liên quan với giải thích chi tiết:

  • Là mảng có tất cả các NULL trong PostgreSQL

Nếu bạn không thể chắc chắn hoàn toàn , bạn có thể rơi trở lại một trong những đắt tiền nhưng an toàn phương thức với unnest() . Như:

(SELECT bool_or(x IS NULL) FROM unnest(arr) x)

hoặc:

EXISTS (SELECT 1 FROM unnest(arr) x WHERE x IS NULL)

Nhưng bạn có thể có nhanh chóng và an toàn với CASE biểu hiện. Sử dụng một số không chắc chắn và quay trở lại phương pháp an toàn nếu nó nên tồn tại. Bạn có thể muốn xử lý trường hợp arr IS NULL riêng biệt. Xem bản trình diễn bên dưới.

Bản trình diễn

SELECT num, arr, expect
     , -1 = ANY(arr) IS NULL                                    AS t_1   --  50 ms
     , (SELECT bool_or(x IS NULL) FROM unnest(arr) x)           AS t_2   -- 754 ms
     , EXISTS (SELECT 1 FROM unnest(arr) x WHERE x IS NULL)     AS t_3   -- 521 ms
     , CASE -1 = ANY(arr)
         WHEN FALSE THEN FALSE
         WHEN TRUE THEN EXISTS (SELECT 1 FROM unnest(arr) x WHERE x IS NULL)
         ELSE NULLIF(arr IS NOT NULL, FALSE)  -- catch arr IS NULL       --  55 ms
      -- ELSE TRUE  -- simpler for columns defined NOT NULL              --  51 ms
       END                                                      AS t_91
     , array_replace(arr, NULL, 0) <> arr                       AS t_93a --  99 ms
     , array_remove(arr, NULL) <> arr                           AS t_93b --  96 ms
     , cardinality(array_remove(arr, NULL)) <> cardinality(arr) AS t_94  --  81 ms
     , COALESCE(array_position(arr, NULL::int), 0) > 0          AS t_95a --  49 ms
     , array_position(arr, NULL) IS NOT NULL                    AS t_95b --  45 ms
     , CASE WHEN arr IS NOT NULL
            THEN array_position(arr, NULL) IS NOT NULL END      AS t_95c --  48 ms
FROM  (
   VALUES (1, '{1,2,NULL}'::int[], true)     -- extended test case
        , (2, '{-1,NULL,2}'      , true)
        , (3, '{NULL}'           , true)
        , (4, '{1,2,3}'          , false)
        , (5, '{-1,2,3}'         , false)
        , (6, NULL               , null)
   ) t(num, arr, expect);

Kết quả:

 num |  arr        | expect | t_1    | t_2  | t_3 | t_91 | t_93a | t_93b | t_94 | t_95a | t_95b | t_95c
-----+-------------+--------+--------+------+-----+------+-------+-------+------+-------+-------+-------
   1 | {1,2,NULL}  | t      | t      | t    | t   | t    | t     | t     | t    | t     | t     | t
   2 | {-1,NULL,2} | t      | f --!! | t    | t   | t    | t     | t     | t    | t     | t     | t
   3 | {NULL}      | t      | t      | t    | t   | t    | t     | t     | t    | t     | t     | t
   4 | {1,2,3}     | f      | f      | f    | f   | f    | f     | f     | f    | f     | f     | f
   5 | {-1,2,3}    | f      | f      | f    | f   | f    | f     | f     | f    | f     | f     | f
   6 | NULL        | NULL   | t --!! | NULL | f   | NULL | NULL  | NULL  | NULL | f     | f     | NULL

Lưu ý rằng array_remove()array_position() không được phép đối với mảng nhiều chiều . Tất cả các biểu thức ở bên phải của t_93a chỉ hoạt động cho mảng 1 chiều.

db <> fiddle here - Postgres 13, với nhiều thử nghiệm hơn
Old sqlfiddle

Thiết lập điểm chuẩn

Thời gian được thêm vào là từ kiểm tra điểm chuẩn với 200 nghìn hàng trong Postgres 9.5 . Đây là thiết lập của tôi:

CREATE TABLE t AS
SELECT row_number() OVER() AS num
     , array_agg(elem) AS arr
     , bool_or(elem IS NULL) AS expected
FROM  (
   SELECT CASE WHEN random() > .95 THEN NULL ELSE g END AS elem  -- 5% NULL VALUES
        , count(*) FILTER (WHERE random() > .8)
                   OVER (ORDER BY g) AS grp  -- avg 5 element per array
   FROM   generate_series (1, 1000000) g  -- increase for big test case
   ) sub
GROUP  BY grp;

Trình bao bọc hàm

Để sử dụng nhiều lần , Tôi sẽ tạo một hàm trong Postgres 9.5 như thế này:

CREATE OR REPLACE FUNCTION f_array_has_null (anyarray)
  RETURNS bool
  LANGUAGE sql IMMUTABLE PARALLEL SAFE AS
 'SELECT array_position($1, NULL) IS NOT NULL';

PARALLEL SAFE chỉ dành cho Postgres 9.6 trở lên.

Sử dụng kiểu đầu vào đa hình, kiểu này phù hợp với bất kỳ kiểu mảng, không chỉ int[] .

Đặt nó thành IMMUTABLE để cho phép tối ưu hóa hiệu suất và các biểu thức chỉ mục.

  • PostgreSQL có hỗ trợ các ảnh ghép "không nhạy cảm với trọng âm" không?

Nhưng đừng làm cho nó STRICT , điều này sẽ vô hiệu hóa "chức năng nội dòng" và làm giảm hiệu suất vì array_position() không phải là STRICT chinh no. Xem:

  • Hàm thực thi nhanh hơn mà không có công cụ sửa đổi STRICT?

Nếu bạn cần nắm bắt trường hợp arr IS NULL :

CREATE OR REPLACE FUNCTION f_array_has_null (anyarray)
  RETURNS bool
  LANGUAGE sql IMMUTABLE PARALLEL SAFE AS
 'SELECT CASE WHEN $1 IS NOT NULL
              THEN array_position($1, NULL) IS NOT NULL END';

Đối với Postgres 9.1 sử dụng t_91 biểu thức từ trên xuống. Phần còn lại áp dụng không thay đổi.

Liên quan chặt chẽ:

  • Làm cách nào để xác định xem NULL có được chứa trong một mảng trong Postgres hay không?


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. ComboBox.ValueMember và DisplayMember

  2. Nhật ký PostgreSQL trên macOS ở đâu?

  3. Làm thế nào để tạo lại một bảng đã xóa với Django Migrations?

  4. Đo điểm chuẩn Giải pháp đám mây PostgreSQL được quản lý:Phần thứ hai - Amazon RDS

  5. Postgres thay đổi trình tự theo cách thủ công