[英]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'
值如下,
["ba18e414-92d3-446b-91b4-67050f891121"]
或["45b90b79-1151-4d8c-8785-4886607524bd", "70b9de47-5e10-42a5-bf30-81c0d4efe6bd", "e1f30960-06eb-41b4-9ca7-49b389defcab", "5cb85419-7fb7-45bd-ae8c-46b3d7ab9154"]
或謝謝
(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.