【发布时间】:2021-06-13 07:07:20
【问题描述】:
我有一个表customers,其结构如下:
id: int
products: text[]
我想创建 SQL 查询来检查是否存在名称包含短语“a”但不包含短语“b”的产品,所以基本上:
product ILIKE "%a%" AND product NOT ILIKE "%b%"
如果我想检查元素是否存在,那么它就像使用 @> 运算符一样简单,但在这里我尝试了 UNNEST 和许多不同的方法,但似乎没有任何效果。
我只想根据这个条件是否包含给定的客户行。你能帮忙吗?
我尝试过这样的事情:
SELECT
*
FROM
customers,
UNNEST(products) AS product
WHERE
product ILIKE '%a%' AND product NOT ILIKE '%b%';
或
SELECT
*
FROM
customers
LEFT JOIN LATERAL (
SELECT * FROM UNNEST(products) AS element
) AS products2 ON TRUE
WHERE
element ILIKE '%a%' AND element NOT ILIKE '%b%';
理论上我可以这样做:
products::TEXT ILIKE '%a%' AND products::TEXT NOT ILIKE '%b%'
但这是一个丑陋的 hack,并不总是有效
【问题讨论】:
-
您显示的第一个查询有什么问题?
-
您可能需要考虑一个正确标准化的模型。不要在应该是一对多关系的事情上滥用数组
-
@a_horse_with_no_name 不幸的是我无法改变它,我必须在这里处理文本数组。它已经是“标准化”数据。我不对这个结构负全部责任,而且我个人只会将产品 ID 存储在那里并按产品 ID 进行查找,但这不是那里发生的事情 :)
-
@jjanes 它不起作用 :) 每当第一个
ILIKE检查返回true它已经返回该行,当第二个ILIKE检查返回 @ 时它甚至不会排除行987654332@。所以基本上它不会连续进行适当的条件检查。相反,它会检查未嵌套结果集的每个子行。
标签: sql postgresql unnest lateral-join