按多列多行条件查找 sql 查询
Find by multiple columns and rows criteria sql query
我在 PostgreSQL 中有路径和条件 table。路径有多个标准,应满足这些标准才能被选中。
路径 table 与 (id
, name
), 条件 table 与 (id
, key
, value
, path_id
)
我需要创建一个 SQL 查询来选择满足两个或更多条件输入(例如,30 岁和男性)的单一路径。我试过 ANY
如下所示。
SELECT p.*, array_agg(c.*) as criteria
FROM paths as p
INNER JOIN criteria as c ON c.path_id = p.id
WHERE (c.key, c.value) = ANY (array[
("age","30"),
("gender","male")
])
GROUP BY p.id
但是只要满足任何一个条件(whether age = 30 or sex = "male"
不是两个),它就会得到一条路径。我用 ALL
替换了 ANY
但这根本 return 没有任何价值。
如果我没听错,您需要将条件移动到 having
子句而不是 where
子句。另外如果你想要满足所有条件的记录,那么你需要单独检查每个条件:
select p.*, array_agg(c.key || ':' || c.value) as criteria
from paths p
inner join criteria c on c.path_id = p.id
group by p.id
having
count(*) filter(where c.key = 'age' and c.value = '30') > 0
and count(*) filter(where c.key = 'gender' and c.value = 'male') > 0
这也可以用两个 EXISTS
条件来表示,这应该是一个退出高效的查询,索引在 criteria(path_id, key, value)
上(但是你失去了聚合所有条件的能力):
select p.*
from paths p
where
exists (
select 1
from criteria c
where c.path_id = p.id and c.key = 'age' and c.value = '30'
)
and exists (
select 1
from criteria c
where c.path_id = p.id and c.key = 'gender' and c.value = 'male'
)
当您处理 key/value 对时,将标准聚合到 JSON 对象中并使用 Postgres 的 json 函数来 select 可能更容易想要:
select p.*, c.*
from paths as p
join (
select path_id, jsonb_object_agg(key, value) as all_criteria
from criteria
group by path_id
having jsonb_object_agg(key, value) @> '{"age": "30", "gender": "male"}'
) c on c.path_id = p.id
我在 PostgreSQL 中有路径和条件 table。路径有多个标准,应满足这些标准才能被选中。
路径 table 与 (id
, name
), 条件 table 与 (id
, key
, value
, path_id
)
我需要创建一个 SQL 查询来选择满足两个或更多条件输入(例如,30 岁和男性)的单一路径。我试过 ANY
如下所示。
SELECT p.*, array_agg(c.*) as criteria
FROM paths as p
INNER JOIN criteria as c ON c.path_id = p.id
WHERE (c.key, c.value) = ANY (array[
("age","30"),
("gender","male")
])
GROUP BY p.id
但是只要满足任何一个条件(whether age = 30 or sex = "male"
不是两个),它就会得到一条路径。我用 ALL
替换了 ANY
但这根本 return 没有任何价值。
如果我没听错,您需要将条件移动到 having
子句而不是 where
子句。另外如果你想要满足所有条件的记录,那么你需要单独检查每个条件:
select p.*, array_agg(c.key || ':' || c.value) as criteria
from paths p
inner join criteria c on c.path_id = p.id
group by p.id
having
count(*) filter(where c.key = 'age' and c.value = '30') > 0
and count(*) filter(where c.key = 'gender' and c.value = 'male') > 0
这也可以用两个 EXISTS
条件来表示,这应该是一个退出高效的查询,索引在 criteria(path_id, key, value)
上(但是你失去了聚合所有条件的能力):
select p.*
from paths p
where
exists (
select 1
from criteria c
where c.path_id = p.id and c.key = 'age' and c.value = '30'
)
and exists (
select 1
from criteria c
where c.path_id = p.id and c.key = 'gender' and c.value = 'male'
)
当您处理 key/value 对时,将标准聚合到 JSON 对象中并使用 Postgres 的 json 函数来 select 可能更容易想要:
select p.*, c.*
from paths as p
join (
select path_id, jsonb_object_agg(key, value) as all_criteria
from criteria
group by path_id
having jsonb_object_agg(key, value) @> '{"age": "30", "gender": "male"}'
) c on c.path_id = p.id