按多个列和行查找条件sql查询

按多个列和行查找条件sql查询,sql,postgresql,relational-division,Sql,Postgresql,Relational Division,我在PostgreSQL中有路径和条件表。路径具有多个要选择的条件 带有(id,name)的路径表,带有(id,key,值,路径id)的条件表 我需要创建一个SQL查询,用于选择满足两个或多个条件输入(例如,30岁和男性性别)的单个路径。我已经尝试了任何,如下所示 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,

我在PostgreSQL中有路径和条件表。路径具有多个要选择的条件

带有(
id
name
)的路径表,带有(
id
key
路径id
)的条件表

我需要创建一个SQL查询,用于选择满足两个或多个条件输入(例如,30岁和男性性别)的单个路径。我已经尝试了
任何
,如下所示

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

但只要满足任何一个标准(无论年龄=30还是性别=“男性”并非两者都满足),就会得到一条路径。我用
ALL
替换了
ANY
,但这根本不返回任何值。

如果我正确地遵循了您的操作,您需要将条件移动到
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
条件表示,这应该是一个有效的退出查询,索引位于
条件(路径id、键、值)
(但随后您失去了聚合所有条件的能力):


在处理键/值对时,将标准聚合为JSON对象并使用Postgres的JSON函数选择所需的对象可能更容易:

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 

您必须添加
计数(c.id)=2
。因为您的条件数组有2个元素。将条件信息存储为
path
表中的
jsonb
列可能更容易。这有一个很好的属性,它可以确保结果中包含两个对,即使“age”或“gender”有多个值@GordonLinoff:通过将
@>
更改为
=
可以很容易地找到那些只有这些键/值对的键/值。在一个json中指定所有条件的能力对我来说是一个优势。谢谢非常感谢。第一个查询适用于我。我不知道你的答案和表演中没有名字的@a_horse_相比如何。我可能需要检查一下。
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