从 Postgres 中的子查询构造值的 ARRAY 并将其用于 WHERE 子句
Construct ARRAY of values from a subquery in Postgres and use it in a WHERE clause
这些是我拥有的两个表的示例:
Table 1
material_id (int) codes (jsonb)
--------------------- -------------------------------
1 ['A-12','B-19','A-14','X-22']
2 ['X-106','A-12','X-22','B-19']
.
.
Table 2
user_id material_list (jsonb)
----------- --------------------
1 [2,3]
2 [1,2]
.
.
Table 1 包含 material 个 ID 和与之关联的一组代码 material。
Table 2 包含用户 ID。每个用户都有一个与之关联的 material 列表,并将其保存在一个 material ID
数组中
我想获取所有 material 具有特定代码的用户 ID 列表。这是我试过的查询,但它引发了语法错误:
SELECT user_id from table2
WHERE material_list ?| array(SELECT material_id
FROM table1 where codes ?| ['A-12','B-19]);
我不知道如何修复它。
这似乎是取消嵌套 json 数组的过程:
select t2.user_id
from table2 t2
where exists (select 1
from table1 t1 join
jsonb_array_elements_text(t2.material_list) j(material_id)
on t1.material_id = j.material_id::int join
jsonb_array_elements_text(t1.codes) j2(code)
on j2.code in ('A-12', 'B-19')
);
Here 是一个 db<>fiddle.
您的查询因多种原因而失败。
首先,['A-12','B-19]
不是有效的 Postgres 文本数组。使用数组常量或数组构造函数:
'{A-12,B-19}'
ARRAY['A-12','B-19']
参见:
- How to pass custom type array to Postgres function
- Pass array literal to PostgreSQL function
接下来,运算符 ?|
要求 text[]
向右,而您提供 int[]
.
最后,无论如何它都行不通,因为运算符 ?|
检查 JSON strings,而不是 numbers。 The manual:
Do any of the strings in the text array exist as top-level keys or array elements?
将 JSON 数组转换为 Postgres 整数数组,然后使用 array overlap operator &&
SELECT user_id
FROM tbl2
WHERE ARRAY(SELECT jsonb_array_elements_text(material_list)::int)
&& ARRAY(SELECT material_id FROM tbl1 where codes ?| array['A-12','B-19']);
我强烈建议更改您的 table 以将 material_list
中的 JSON 数组永久转换为 Postgres 整数数组 (int[]
)。参见:
- Altering JSON column to INTEGER[] ARRAY
- How to turn JSON array into Postgres array?
然后查询变得更简单:
SELECT user_id
FROM tbl2
WHERE material_list && ARRAY(SELECT material_id FROM tbl1 where codes ?| '{A-12,B-19}');
db<>fiddle here
或者 - 我敢说吗? - 正确地正常化你的关系设计。参见:
- How to implement a many-to-many relationship in PostgreSQL?
这些是我拥有的两个表的示例:
Table 1
material_id (int) codes (jsonb)
--------------------- -------------------------------
1 ['A-12','B-19','A-14','X-22']
2 ['X-106','A-12','X-22','B-19']
.
.
Table 2
user_id material_list (jsonb)
----------- --------------------
1 [2,3]
2 [1,2]
.
.
Table 1 包含 material 个 ID 和与之关联的一组代码 material。
Table 2 包含用户 ID。每个用户都有一个与之关联的 material 列表,并将其保存在一个 material ID
数组中我想获取所有 material 具有特定代码的用户 ID 列表。这是我试过的查询,但它引发了语法错误:
SELECT user_id from table2
WHERE material_list ?| array(SELECT material_id
FROM table1 where codes ?| ['A-12','B-19]);
我不知道如何修复它。
这似乎是取消嵌套 json 数组的过程:
select t2.user_id
from table2 t2
where exists (select 1
from table1 t1 join
jsonb_array_elements_text(t2.material_list) j(material_id)
on t1.material_id = j.material_id::int join
jsonb_array_elements_text(t1.codes) j2(code)
on j2.code in ('A-12', 'B-19')
);
Here 是一个 db<>fiddle.
您的查询因多种原因而失败。
首先,['A-12','B-19]
不是有效的 Postgres 文本数组。使用数组常量或数组构造函数:
'{A-12,B-19}'
ARRAY['A-12','B-19']
参见:
- How to pass custom type array to Postgres function
- Pass array literal to PostgreSQL function
接下来,运算符 ?|
要求 text[]
向右,而您提供 int[]
.
最后,无论如何它都行不通,因为运算符 ?|
检查 JSON strings,而不是 numbers。 The manual:
Do any of the strings in the text array exist as top-level keys or array elements?
将 JSON 数组转换为 Postgres 整数数组,然后使用 array overlap operator &&
SELECT user_id
FROM tbl2
WHERE ARRAY(SELECT jsonb_array_elements_text(material_list)::int)
&& ARRAY(SELECT material_id FROM tbl1 where codes ?| array['A-12','B-19']);
我强烈建议更改您的 table 以将 material_list
中的 JSON 数组永久转换为 Postgres 整数数组 (int[]
)。参见:
- Altering JSON column to INTEGER[] ARRAY
- How to turn JSON array into Postgres array?
然后查询变得更简单:
SELECT user_id
FROM tbl2
WHERE material_list && ARRAY(SELECT material_id FROM tbl1 where codes ?| '{A-12,B-19}');
db<>fiddle here
或者 - 我敢说吗? - 正确地正常化你的关系设计。参见:
- How to implement a many-to-many relationship in PostgreSQL?