检查Postgres数组中是否存在值


192

使用Postgres 9.0,我需要一种方法来测试给定数组中是否存在值。到目前为止,我想到的是这样的:

select '{1,2,3}'::int[] @> (ARRAY[]::int[] || value_variable::int)

但是我一直认为应该有一个更简单的方法,我只是看不到它。这似乎更好:

select '{1,2,3}'::int[] @> ARRAY[value_variable::int]

我相信就足够了。但是,如果您还有其他方法,请分享!

Answers:


320

ANY构造更简单:

SELECT value_variable = ANY ('{1,2,3}'::int[])

ANY(在括号之间)的右操作数可以是集合(例如,子查询的结果)数组。有几种使用方法:

重要的区别:(数组运算符<@@>&&。等人)中期望阵列类型作为操作数和支撑GIN或GiST索引中的PostgreSQL标准分布,而ANY构建体预期的元件为左操作数,并且不支持这些索引类型。例:

这些都不适合NULL元素。测试NULL


谢谢。必须跳过手册的那部分。这很好。它具有自动铸造的副作用。例如:SELECT 1 :: smallint = ANY('{1,2,3}':: int [])有效。只要确保将ANY()放在表达式的右侧即可。
Mike Starov 2012年

感谢你的回答。在我的查询在本地工作时遇到了一个问题,但是在heroku中抛出了此消息ANY/ALL (array) requires array on right side,添加::int[]了魅力。
kinduff 2012年

其中S.employee_id <@ ANY('“ + employeeIDsArray +”':: int [])这将返回PSQLException:错误:缺少尺寸值
Ramprasad 2014年

3
尽管这是互联网时代的恐龙问题,但应该让像我这样的慢家伙知道'something' = ANY(some_array)也可以在WHERE子句中使用。由于仅Crom知道的原因,最近四年来我一直在考虑不能在WHERE子句中使用数组比较器。那些日子已经过去了。(我小时候掉在头上,所以也许就是我)。
GT。

1
@GT .:要点:任何 boolean表达式均可WHERE子句中使用-Crom愿意。
Erwin Brandstetter

90

当心我陷入的陷阱:当检查数组中是否不存在某些值时,您不应该这样做:

SELECT value_variable != ANY('{1,2,3}'::int[])

但是使用

SELECT value_variable != ALL('{1,2,3}'::int[])

代替。


2
一种双重否定的;注意他对ALLvsANY
vol7ron的

43
SELECT NOT value_variable = ANY('{1,2,3}'::int[])可能是更具可读性
的Ondrej布达

28

但是如果您还有其他方法可以分享,请与我们分享。

您可以比较两个数组。如果左侧数组中的任何值与右侧数组中的值重叠,则它将返回true。这有点骇人听闻,但确实有效。

SELECT '{1}'   && '{1,2,3}'::int[];  -- true
SELECT '{1,4}' && '{1,2,3}'::int[];  -- true
SELECT '{4}'   && '{1,2,3}'::int[];  -- false
  • 在第一个和第二个查询中,值1在正确的数组中
  • 请注意,第二个查询是true,即使该值4未包含在正确的数组中
  • 对于第三个查询,左数组(即4)中没有值在右数组中,因此它返回false

如何从另一个表中搜索列以在数组中具有值?例如,从style_id输入(从id = 1的用户中选择首选项)限制为1的啤酒中选择*;style_id是整数数据类型;首选项是integer []我得到这个错误错误:运算符不存在:整数=整数[]第1行:从style_id输入的啤酒中选择*(选择首选项f ... ^提示:没有运算符与给定的名称和参数类型匹配(s)。您可能需要添加显式类型转换
HP

@HP有多种方法可以解决该问题,您应该提出一个新问题
vol7ron '16

您确定没有现有问题吗?@ vol7ron
HP

@HP完全没有,但是评论仅用于提出问题或答案的评论;通常会添加更多信息或寻求更多未解决的信息。您要提出的问题与此答案无关。我认为通过将您的问题作为新帖子而不是在评论中进行,您会更幸运;)
vol7ron 16/04/29

@HP(如果您尚未发布问题)可以在此处查看:sqlfiddle.com/#!15/144cd/3,以获取所需操作的示例-问题不同,因为您需要取消嵌套数组的问题。
vol7ron '16

4

unnest也可以使用。它将数组扩展为一组行,然后简单地检查一个值是否存在与使用INor 一样简单NOT IN

例如

  1. id => uuid

  2. exception_list_ids => uuid []

select * from table where id NOT IN (select unnest(exception_list_ids) from table2)


是。请注意,在我的查询计划中,SELECT UNNEST不如= ANY好。我建议检查查询计划,看看您是否得到了想要/期望的东西。
罗布·比格雷夫

3

当寻找数组中元素的存在时,需要适当的转换才能传递postgres的SQL解析器。这是一个在join子句中使用数组包含运算符的示例查询:

为简单起见,我只列出相关部分:

table1 other_name text[]; -- is an array of text

显示的SQL的连接部分

from table1 t1 join table2 t2 on t1.other_name::text[] @> ARRAY[t2.panel::text]

以下也适用

on t2.panel = ANY(t1.other_name)

我只是在猜测是否需要额外的转换,因为解析不必获取表定义来确定列的确切类型。其他人请对此发表评论。


0

嗨,一个对我来说很好,也许对某人有用

从your_table中选择*,其中array_column :: text类似于ANY(ARRAY ['%text_to_search%':: text]);

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.