【发布时间】:2020-06-01 09:16:55
【问题描述】:
我尝试编写一个查询,在该查询中,我选择基于 LIKE 模式的行,该模式必须与数组的任何条目都不匹配。我有的是现在的
SELECT * FROM mytable WHERE
NOT (EXISTS (SELECT * from unnest(a) WHERE unnest LIKE '%XYZ%' )))
其实我想要的是pairs——所以更像
SELECT * FROM mytable WHERE
NOT (
(EXISTS (select * from unnest(a) as A, unnest(b) as B WHERE A||B LIKE '%xyz%abc%' )) OR
(EXISTS (select * from unnest(a) as A, unnest(b) as B WHERE A||B LIKE '%abc%xyz%' ))
)
这对我有用,但看起来相当笨拙。有没有更漂亮/更有效的解决方案?我发现最讨厌的是 SELECT 作为 WHERE 子句的一部分来展开数组。
几点:
- 在我的情况下,
xyz和abc不会作为子字符串一起出现在单个数组条目中(例如,没有像xyzblaabcexists 这样的东西) - 两个数组的元素数量完全相同(它们实际上是从另一个查询派生的)
- 没有空元素(但即使这样仍然可以工作,因为我没有一对
abc和xyz)
编辑:
澄清:不应返回包含 A 为 {rxyz,foo, bar} 和 B 为 {other, abc, this} 的行,因为它在一个数组中包含 rxyz,在另一个数组中包含 abc
例子:
SELECT * FROM(
SELECT *
FROM (select 1 as ID, '{rxyz,foo,bar}'::varchar[] as a, '{abc,other,this}'::varchar[] as b) row1 UNION
SELECT *
FROM (select 2 as ID, '{rxyz,foo,bar}'::varchar[] as a, '{other,rabc,this}'::varchar[] as b) row1 UNION
SELECT *
FROM (select 3 as ID, '{else,foo,bar}'::varchar[] as a, '{abc,other,this}'::varchar[] as b) row2
) mytable
WHERE
NOT (
(EXISTS (select * from unnest(a) as A, unnest(b) as B WHERE A||'-|-'||B LIKE '%xyz%-|-%abc%' OR B||'-|-'||A LIKE '%xyz%-|-%abc%' )))
仅返回第 3 行。在我的用例中,我可以保证 -|- 不是这两个列表的一部分,因此可以将它们分开。
【问题讨论】:
-
*“这行得通……” - 是吗?见答案。
-
那么在this fiddle 中,只有 1-3 个符合条件?
-
@ErwinBrandstetter 在那一个中,除了 4 之外的所有内容都应该返回。
-
对不起,但这并没有加起来。您应用于小提琴的查询返回不同的集合:dbfiddle here 请提供您想要实现的准确定义.
-
@ErwinBrandstetter 正如提到的
abc和xyz,在我的情况下,它们不会属于同一个字符串。在您的示例中,它们位于 7 和 8 中-对不起,我错过了。所以 4、7 和 8 被“正确”过滤掉了。这些数组实际上是array_agg()对其他数据的结果。所以我知道它们的大小总是一样的。
标签: sql arrays postgresql unnest