将包含列表的记录值与 Postgres 中的列值进行比较
Posted
技术标签:
【中文标题】将包含列表的记录值与 Postgres 中的列值进行比较【英文标题】:Compare a record value containing a list with column values in Postgres 【发布时间】:2021-02-01 20:50:57 【问题描述】:我需要编写一个选择语句,该语句必须使用一个列值将两个表链接在一起,该列值包含一个由“,”分隔的项目列表,以及一个包含每个项目单独列出的列,也可以使用过滤结果那些相同的列。示例:
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。如果没有 storagid 与所有请求的项目相关联,则该请求将被忽略。又名:
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 的请求;还是我做错了?
【问题讨论】:
Is adding the ‘tbl’ prefix to table names really a problem? 【参考方案1】:您可以将所有存储项聚合到一个数组中,将请求项转换为适当的数组,然后加入这些数组:
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
【讨论】:
空格是错字。幸运的是,我可以确认项目列表没有空格,至少目前是这样;但如果来源碰巧改变了他们管理数据的方式,我将不得不记住这一点。 @tmattson: 那么你应该使用string_to_array
,因为它比正则表达式更快
尝试了这种方法,到目前为止一切顺利。我遇到的唯一问题是 array_agg 创建了一个字符可变数组,而 string_to_array 创建了一个文本数组。通过将 string_to_array 类型转换为字符变化来轻松修复:“string_to_array(requesteditems,',')::character varying[]”以上是关于将包含列表的记录值与 Postgres 中的列值进行比较的主要内容,如果未能解决你的问题,请参考以下文章
当列表值与Pyspark数据帧中的列值的子字符串匹配时,填充新列
如何在带有 Postgres 的动态框架中使用窗口函数中的列值?