PostgreSQL - 如何找到记录与其匹配的值高于给定值的行?

PostgreSQL - How to find the row with a record that matches it with a value higher than given value?

假设我有两个具有一对多关系的表。

Table A(用户): 身份证, 名称文本

Table B(技能): 身份证, user_id 情报, skill_name 文本, skill_level 积分

每个用户可能有多种技能。现在我希望收集至少在一定水平上具有某种技能的用户,并且可能具有符合条件的所有技能的用户。

例如,假设我的数据库中有以下数据:

用户:

id | name 
1  | Merlin
2  | Morgan

技能:

id | user_id | skill_name    | skill_level 
1  | 1       | Fireball      | 2 
2  | 1       | Thunderbolt   | 3 
2  | 2       | Thunderbolt   | 2 
2  | 2       | Firestorm     | 1 
2  | 2       | Curse         | 3 

如果我搜索拥有 2 级或更高雷电的用户,我应该同时获得 Merlin 和 Morgan;如果我搜索同时知道 1 级或更高级别的雷电和 2 级或更高级别的诅咒的用户,那么只有摩根应该出现。

另外,我希望结果也能包含用户所有技能的内容。现在我正在使用 ARRAY_AGG(JSON_BUILD_OBJECT('skill_name', skill_name, 'skill_level', skill_level')按用户id收集所有技能。但是我不知道如何根据我获得的那些技能来过滤数据。

一种方法使用聚合。一项技能:

select user_id
from skills
group by user_id
having count(*) filter (where skill_name = 'thunderbold' and skill_level >= 2) > 0;

而对于多个技能,只需添加更多子句:

select user_id
from skills
group by user_id
having count(*) filter (where skill_name = 'thunderbold' and skill_level >= 1) > 0 and
       count(*) filter (where skill_name = 'curse' and skill_level >= 2) > 0 ;

本returns本user_id。您可以重新加入用户 table 以获取名称。

一种方法使用聚合和 having 子句来过滤技能名称和级别。布尔聚合函数在这里派上用场:

select u.*, 
    jsonb_agg(jsonb_build_object('skill_name', skill_name, 'skill_level', skill_level)) as skills
from users u
inner join skills s on s.user_id = u.id
group by u.id
having bool_or(s.skill_name = 'Thunderbolt' and s.skill_level >= 1)
   and bool_or(s.skill_name = 'Curse'       and s.skill_level >= 2)

这还会将一列添加到结果集中,称为 skills,这是一个 JSONB 数组,其中包含每个技能名称和级别的一个对象,如您的问题中所要求的:请注意它生成一个 JSON(B) 数组而不是一个 JSON 对象数组更有意义,正如您最初想要的那样。