将包含列表的记录值与 Postgres 中的列值进行比较

Compare a record value containing a list with column values in Postgres

我需要编写一个 select 语句,该语句必须 link 两个 table 一起使用一个包含由 ',' 和分隔的项目列表的列值每个项目单独列出的一列,也可以使用这些相同的列过滤结果。示例:

tbl_requests
requestid | requesteditems
1234567   | laptop,monitor,mouse
1234568   | laptop,dock
1234569   | monitor,keyboard,mouse
1234570   | monitor,dock,keyboard

tbl_storage
storageid | item
123       | laptop
123       | monitor
123       | mouse
123       | keyboard
154       | laptop
154       | dock

我无法控制数据插入请求的方式 table。无论如何,我需要一个 select 语句来 return 每个 requestid 和一个包含该请求的所有 requesteditems 的单个 storageid。如果没有 storagid 与所有请求的项目相关联,则该请求将被忽略。又名:

Result Table
requestid | storageid
1234567   | 123
1234568   | 154
1234569   | 123

不应包括 1234570,因为存储 ID 与所有请求的项目都没有关联。

据我所知,我可以 link 使用 unnest 的两个 table 如下:

select distinct on (r.requestid) r.request, s.storageid from tbl_requests r, unnest(string_to_array(r.requesteditems, ',')) r(items)
join tbl_storage s on s.item=r.items

这让我很接近,但结果可能会有所不同,因为请求 1234568 可能 return 123 或 154 作为 storageid,因为列出的第一个项目是笔记本电脑,这两个 storageid 都有与笔记本电脑关联的记录。此外,请求 1234570 将 return 使用存储 ID 123 编辑,因为该存储 ID 确实具有与之关联的监视器。

是否可以向上述查询添加条件以确保唯一的请求 returned 是具有与 requesteditem 中列出的每个项目关联的 storageid 的请求;还是我做错了?

您可以将所有存储项聚合到一个数组中,将请求的项转换为适当的数组,然后加入这些数组:

with storage as (
  select storageid, array_agg(item) items
  from tbl_storage
  group by storageid 
), requests as (
  select requestid, string_to_array(requesteditems,',') as items
  from tbl_requests
)
select r.requestid, s.storageid
from requests r
  join storage s on s.items @> r.items 

如果存储项 (s.items) 包含数组中包含请求项的所有元素,则表达式 s.items @> r.items 为真。

Online example