SQL 查询 where has children with conditions

SQL query where has children with conditions

假设我有:

现在我想过滤掉任何 parent id 的 ,它至少有一个 child 并且:

其中一个 child 的 intelligence 为 5,health 为 4,或者一个 child 的 intelligence 为 5,另一个 child 有 health 的 4.

如何在 PostgreSQL 中查询? 谢谢

如果您只想要 parents 信息:

SELECT 
  DISTINCT parents.id, parents.name 
FROM 
  parents 
  LEFT JOIN attributes ON parents.id = attributes.parent_id 
WHERE 
  (attribute = 'intelligence' AND attribute_value = 5)
   OR (attribute = 'health' AND attribute_value = 4)

首先我们需要加入表 -- 像这样

select p.id as p_id, p.name as parent_name,
       k.* -- we won't need this in later versions
from parent p
join kidatt k on p.id = k.parent_id

现在我们有两个我们关心的属性——让我们进行一个查询来显示那些

select p.id as p_id, p.name as parent_name,
       case when k.attribute = 'intelligence' and k.attribute_value = 5 then 1 else 0 end as has_a1,
       case when k.attribute = 'health' and k.attribute_value = 4 then 1 else 0 end as has_a2
from parent p
join kidatt k on p.id = k.parent_id

我们现在有一个查询,其中每行都有一个 1

现在我们按 parent.

分组
select p.id as p_id, p.name as parent_name,
       SUM(case when k.attribute = 'intelligence' and k.attribute_value = 5 then 1 else 0 end) as has_a1,
       SUM(case when k.attribute = 'health' and k.attribute_value = 4 then 1 else 0 end) as has_a2
from parent p
join kidatt k on p.id = k.parent_id
group by p.id, p.name

现在我们有一个查询,如果一个或多个 child 有 a1 和 a2 大于 0。

现在select结果

select * 
from (
  select p.id as p_id, p.name as parent_name,
       SUM(case when k.attribute = 'intelligence' and k.attribute_value = 5 then 1 else 0 end) as has_a1,
       SUM(case when k.attribute = 'health' and k.attribute_value = 4 then 1 else 0 end) as has_a2
  from parent p
  join kidatt k on p.id = k.parent_id
  group by p.id, p.name
)
where has_a1 > 0 and has_a2 > 0

注意——我写这个查询并不是为了最好的解决这个问题的方法——相反,我写它的方式是向您展示如何在 SQL 中“思考”并通过一系列步骤解决问题。

我必须进行测试才能确定,但​​我希望这是执行此查询的最快方法(取决于数据和索引等)

select distinct p.id as p_id, p.name as parent_name,          
from parent p
join kidatt k on p.id = k.parent_id
where k.attribute = 'intelligence' and k.attribute_value = 5

intersect

select distinct p.id as p_id, p.name as parent_name,          
from parent p
join kidatt k on p.id = k.parent_id
where k.attribute = 'health' and k.attribute_value = 4 

你可以做

的交集
  • parents children 智力 5
  • parents children 生命值 4
(SELECT parent_id 
 FROM tab
 WHERE attribute = 'intelligence'
   AND attribute_value = 5       )
INTERSECT
(SELECT parent_id 
 FROM tab
 WHERE attribute = 'health'
   AND attribute_value = 4       )