我在PostgreSQL 9.6数据库中有一个表:
CREATE TABLE new_table (
column_name varchar(255)[],
name varchar(40)
);
INSERT INTO new_table VALUES
('{one, two}' , 'first_user'),
('{other, two}', 'second_user'),
('{one, more}' , 'third_user');
我有一个数组数组(2D数组),并希望找到表column_name
匹配任何包含的1D数组的表的所有行。我喜欢这样的事情:
select *
from new_table as s
where s.column_name = any('{{"one", "two"}, {"one", "more"}, {"two", "five"}}')
但这给了我错误:
ERROR: could not find array type for data type text[]
我想要的结果:
column_name | name
------------+--------------
{one,two} | first_user
{one,more} | third_user
任何人都有任何想法?
答案 0 :(得分:0)
使用数组运算符与运算符一起工作:
t=# select *
from new_table as s
where s.column_name <@ '{{"one", "two"}, {"one", "more"}, {"two", "five"}}';
column_name | name
-------------+------------
{one,two} | first_user
{one,more} | third_user
(2 rows)
我认为https://www.postgresql.org/docs/current/static/functions-comparisons.html#idm46428706346880可能有一些注释,表达式不是数组,您无法将其用于此类比较
<强>更新强>
能够通过1维排除&#34;排除数组&#34;并使用in
comarison的结果集,使用Pavel Stěhule建议的function:
t=# select * from new_table
where column_name in (
select reduce_dim('{{one, two}, {two, more}, {one, five}}'::character varying[])
);
column_name | name
-------------+------------
{one,two} | first_user
(1 row)
答案 1 :(得分:0)
为了记录,你的表面错误:
ERROR: could not find array type for data type text[]
..将通过明确的演员而消失。像:
...
WHERE column_name = any('{{"one", "two"}, {"one", "more"}, {"two", "five"}}'::varchar[])
但那不解决了潜在的问题:
ERROR: operator does not exist: character varying[] = character varying
Postgres对多维数组的支持可能令人困惑。实际上,varchar(255)[]
在内部解析为与varchar(255)[][]
完全相同的数据类型。
每个数组值的 元素 类型为varchar
(不是varchar[]
)。 ANY
构造有效地忽略了数组维度。
The manual:
数组比较逐个元素地比较数组内容
要实现您的目标,您需要将2D阵列替换为1D阵列。每个数据库创建此函数一次:
CREATE OR REPLACE FUNCTION unnest_2d_1d(ANYARRAY, OUT a ANYARRAY)
RETURNS SETOF ANYARRAY AS
$func$
BEGIN
FOREACH a SLICE 1 IN ARRAY $1 LOOP
RETURN NEXT;
END LOOP;
END
$func$ LANGUAGE plpgsql IMMUTABLE STRICT;
进一步阅读:
现在,所有这些查询都有效:
SELECT t.*
FROM unnest_2d_1d('{{"one", "two"}, {"one", "more"}, {"two", "five"}}'::varchar[]) a(column_name)
JOIN new_table t USING (column_name);
或者:
SELECT t.*
FROM new_table t
WHERE column_name = ANY ((SELECT unnest_2d_1d('{{"one", "two"}, {"one", "more"}, {"two", "five"}}'::varchar[])));
或者:
...
WHERE column_name IN ((SELECT unnest_2d_1d('{{"one", "two"}, {"one", "more"}, {"two", "five"}}'::varchar[])));
dbfiddle here
相关:
这是极少数情况下,数组列上的btree索引可能有用:
CREATE INDEX ON new_table(column_name);
Postgres中varchar(255)
没有什么特别之处。我大多只使用text
。参见: