按多列多行条件查找 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 

Online example