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 对象数组更有意义,正如您最初想要的那样。
假设我有两个具有一对多关系的表。
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 对象数组更有意义,正如您最初想要的那样。