簡體   English   中英

Postgres:如何為 s json 數組元素創建一個 not in 語句

[英]Postgres: how to create a not in statement for s json array element

第一個名為dev的表的表模式的提取,

開發者編號 員工姓名 JSON 身份證
ef7fd5df-7881-470d-bc7d-846211df0344 湯姆 {“sourcedevIds”:[],“sourcedepartmentId”:[“edfgerg-4534-4frg-5665-bgfbn645”,“546t5gg43-78ik-m78i-345t34e-h56e5”]}
345r34-2345-56yt-78ui-343trtrfg567 約翰 {"sourcedevIds":["wedfrtg-7890-3trr-6887-rte45R3"],"sourcedepartmentId":["werefr-3454-56tyy-2343-rt456y","34e27-2343-456te-23ewd-89iol","343rfe -34rde-4reft-3edq-343r322"]}

注意: uuid 在這里只是虛擬值。

所以我需要做的是在dev.JSON ID ->> 'sourcedepartmentId'下創建一個not in語句或類似語句,以僅獲取不具有以下 uuid(注意:查詢中添加的虛擬值)的員工姓名作為一個元素中的 JSON 數據(即 uuid 值)。

例如我寫的當前查詢如下,

(dev.JSON ID ->> 'sourcedepartmentId')::uuid not in 
                                  (  '34e27-2343-456te-23ewd-89iol',
                                     '3retwut5-78ut-42dw-wu67-w234rtyu7',
                                     '5tvgr23t-23detrg-34fe-4gt66-23edw345',
                                     '546t5gg43-78ik-m78i-345t34e-h56e5',
                                     '343rfe-34rde-4reft-3edq-343r322'
                                    )

我得到的錯誤是

invalid input syntax for type uuid: "["edfgerg-4534-4frg-5665-bgfbn645"]" 

然后我嘗試了以下,

json_array_elements_text((dev.JSON ID ->> 'sourcedepartmentId')::json) not in 
                                  (  '34e27-2343-456te-23ewd-89iol',
                                     '3retwut5-78ut-42dw-wu67-w234rtyu7',
                                     '5tvgr23t-23detrg-34fe-4gt66-23edw345',
                                     '546t5gg43-78ik-m78i-345t34e-h56e5',
                                     '343rfe-34rde-4reft-3edq-343r322'
                                    )

我認為第一個查詢之前的結果不是只有數組的第一個值(我試圖查詢這個返回的值,是的,它只返回數組的第一個值。雖然還有其他值。)

任何幫助將非常感激。 謝謝


解決方案c后的not in語句查看sub id的

(dev.subID ->> 'sourcedepartmentId' ->>0)::uuid not in 
                               (  '34e27-2343-456te-23ewd-89iol',
                                  '3retwut5-78ut-42dw-wu67-w234rtyu7',
                                  '5tvgr23t-23detrg-34fe-4gt66-23edw345',
                                  '546t5gg43-78ik-m78i-345t34e-h56e5',
                                  '343rfe-34rde-4reft-3edq-343r322'
                                )   

另外,請注意d.json_id -> 'sourcedepartmentId'值如下,

  • 只有一個 uuid 值。 示例: ["ba18e414-92d3-446b-91b4-67050f891121"]
  • 多個 uuid 值作為一個數組。 例子: ["45b90b79-1151-4d8c-8785-4886607524bd", "70b9de47-5e10-42a5-bf30-81c0d4efe6bd", "e1f30960-06eb-41b4-9ca7-49b389defcab", "5cb85419-7fb7-45bd-ae8c-46b3d7ab9154"]
  • null 或空值。

謝謝

(a) (dev.JSON ID ->> 'sourcedepartmentId')將 json 數組作為帶有方括號的文本返回,因此它不能被轉換為uuid ,這會引發您得到的錯誤。

(b) json_array_elements_text(dev."JSON ID")應該返回一組可以轉換為uuid的文本,但它不能直接插入到查詢的WHERE子句中,因為在WHERE中不允許使用集合返回函數。

(c) 一種可能的解決辦法是:

SELECT ...
  FROM dev
 CROSS JOIN LATERAL json_array_elements_text(dev."JSON ID" -> 'sourcedepartmentId') AS j(data)
 WHERE j.data :: uuid NOT IN (  '34e27-2343-456te-23ewd-89iol',
                                '3retwut5-78ut-42dw-wu67-w234rtyu7',
                                '5tvgr23t-23detrg-34fe-4gt66-23edw345',
                                '546t5gg43-78ik-m78i-345t34e-h56e5',
                                '343rfe-34rde-4reft-3edq-343r322'
                             )

(c) 正如@Laurenz 所解釋的,這個解決方案不能真正高效。 沒有與大多數sql 數組運算符等效的 json 運算符,因此查詢 json ZA3CBC3F9D0CE2F2C1754E1B67D1 通常並不容易。

(d) 在使用以下條件進行查詢時,將sourcedepartmentId數據存儲在uuid[]類型的專用列中並使用專用gin索引可能會更有效:

NOT sourcedepartmentId && array['34e27-2343-456te-23ewd-89iol',
                                '3retwut5-78ut-42dw-wu67-w234rtyu7',
                                '5tvgr23t-23detrg-34fe-4gt66-23edw345',
                                '546t5gg43-78ik-m78i-345t34e-h56e5',
                                '343rfe-34rde-4reft-3edq-343r322'
                               ] :: uuid[]

(e) 如果您無法更改開發表定義,我建議創建一個專用dev將 json 數組轉換為 uuid 數組。 然后這個 function 可用於索引和查詢您的數據:

CREATE OR REPLACE FUNCTION json_to_uuid_array(data json)
RETURNS uuid[] LANGUAGE sql AS
$$
  SELECT ARRAY(SELECT json_array_elements_text(data -> 'sourcedepartmentId')) :: uuid[] ;
$$ ;

CREATE INDEX IF NOT EXISTS sourcedepartmentId ON dev USING gin (json_to_uuid_array("JSON ID")) ;

SELECT ...
  FROM dev
 WHERE NOT json_to_uuid_array(dev."JSON ID") 
       && array['34e27-2343-456te-23ewd-89iol',
                '3retwut5-78ut-42dw-wu67-w234rtyu7',
                '5tvgr23t-23detrg-34fe-4gt66-23edw345',
                '546t5gg43-78ik-m78i-345t34e-h56e5',
                '343rfe-34rde-4reft-3edq-343r322'
               ] :: uuid[] ;

我會使用 NOT EXISTS 條件來執行此操作,該條件使用IN條件檢查是否存在:

select *
from dev d
where not exists (select *
                  from jsonb_array_elements_text(d.json_id -> 'sourcedepartmentId') as s(dept_id)
                  where s.dept_id in ('34e27-2343-456te-23ewd-89iol',
                                      '3retwut5-78ut-42dw-wu67-w234rtyu7',
                                      '5tvgr23t-23detrg-34fe-4gt66-23edw345',
                                      '546t5gg43-78ik-m78i-345t34e-h56e5',
                                      '343rfe-34rde-4reft-3edq-343r322')
                  )

這假定列json_id被定義為jsonb (它應該是)。 如果不是,請改用json_array_elements_text()


如果您還需要應對sourcedepartmentId可能是單個值而不是數組這一事實,則需要使內部查詢更加復雜,以不同方式處理這兩種情況。

select *
from dev d
where not exists (select *
                  from ( 
                    select * 
                    from jsonb_array_elements_text(d.json_id -> 'sourcedepartmentId')
                    where jsonb_typeof(d.json_id -> 'sourcedepartmentId') = 'array'
                    union all
                    select d.json_id ->> 'sourcedepartmentId'
                    where jsonb_typeof(d.json_id -> 'sourcedepartmentId') = 'string'
                  )  as s(dept_id)
                  where s.dept_id in (....)
                 )

同樣,如果您沒有使用推薦的jsonb類型,則必須改用json_typeof()

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM