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

Postgresql 将包含列表的记录值与Postgres中的列值进行比较,postgresql,postgresql-12,Postgresql,Postgresql 12,我需要编写一个select语句,该语句必须使用一个列值将两个表链接在一起,其中一个列值包含由“,”分隔的项目列表,另一个列包含每个单独列出的项目,还可以使用这些列过滤结果。例如: tbl_requests requestid | requesteditems 1234567 | laptop,monitor,mouse 1234568 | laptop,dock 1234569 | monitor,keyboard,mouse 1234570 | monitor,dock,key

我需要编写一个select语句,该语句必须使用一个列值将两个表链接在一起,其中一个列值包含由“,”分隔的项目列表,另一个列包含每个单独列出的项目,还可以使用这些列过滤结果。例如:

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
我无法控制如何将数据插入请求表。无论如何,我需要一个select语句来返回每个requestid和一个storageid,其中包含该请求的所有requesteditems。如果没有任何storagid与所有requesteditems关联,则该请求将被忽略。又名:

Result Table
requestid | storageid
1234567   | 123
1234568   | 154
1234569   | 123
不应包括1234570,因为存储id未与所有请求的项目关联

就我所知,我可以使用unnest链接两个表,如下所示:

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可能会返回123或154作为storageid,因为列出的第一项是笔记本电脑,这两个storageid都有与笔记本电脑相关的记录。此外,请求1234570将与storageid 123一起返回,因为该存储id确实有与其关联的监视器


是否可以在上述查询中添加条件,以确保返回的请求仅是那些具有与requesteditem中列出的每个项关联的storageid的请求;还是我的想法完全错了?

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

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
为真


空白是一个打字错误。幸运的是,我可以确认项目列表没有空格,至少目前是这样;但是,如果源代码碰巧改变了他们管理数据的方式,我必须记住这一点。@tmattson:那么你应该使用
string\u to\u array
,因为这比regex快,这是一种可行的方法,目前为止效果很好。我遇到的唯一障碍是array\u agg创建了一个字符可变数组,而string\u to\u数组创建了一个文本数组。通过将字符串“”转换为“”数组作为字符变量来轻松修复:“字符串“”转换为“”数组(requesteditems,,')::character variabling[]”