hibernate 是否可以按公共列对SQL连接结果进行分组?请参阅说明

qcuzuvrc  于 2022-11-14  发布在  其他
关注(0)|答案(2)|浏览(162)

我对数据库非常生疏,在过去的6-8年里,我没有机会太多地使用它们,所以有些事情对我来说是不确定的。
让我们假设我有一个简单的双向一对多情况:

Parent
------
id

Child
-----
id
age
parent_id

我想执行一个查询,该查询将返回符合某些规则的所有父代以及匹配的子代。
例如,让我们假设我们有

Parent: [Child (age 5), Child (age 8), Child (age 10)]
Parent: [Child (age 8), Child (age 15)]
Parent: [Child (age 20)]

我想要获得父母和他们的孩子一起,例如按年龄(10岁以下)过滤。
这种情况下会出现一个带有WHERE语句的连接--类似于:

SELECT Parent.id, Child.id, Child.age
    FROM Parent LEFT JOIN Child ON Parent.id = Child.parent_id 
    WHERE Child.age < 10;

这样做可以很好地工作,并返回3个条目--父项1的两行以及与规则匹配的子项,父项2及其子项的一行。
然而,我的问题是-我可以根据家长ID以某种方式将其分组吗?我可以使用LIMIT来限制家长人数吗?(例如,在本例中,限制2将返回所有结果-因为有两个父项符合条件)
后台环境--我正在尝试用Java、Hibernate和Postgres数据库来实现这一点。我使用OneToMany/ManyToOne关系和CriteriaQuery来询问数据库。

fnvucqvd

fnvucqvd1#

如果我理解你的意思,你想限制两个父母,但这可能意味着超过两行,因为一个父母可以有一个以上的10岁以下的孩子?如果是这样的话,count分析函数可以开始对父代进行编号,您可以通过获取结果计数<=2来设置限制:

with qualifying_parents as (
  select
    c.id, c.age, c.parent_id,
    count (parent_id) over (partition by parent_id) as cnt
  from
    child c
    join parent p on c.parent_id = p.id
  where
    c.age < 10
)
select id as child_id, age, parent_id
from qualifying_parents
where cnt <= 2

这将为您提供示例中的三行,但只有两个不同的父ID。
此外,在本例中,parent表是不必要的,但我假设它有更多的属性,而不仅仅是您打算在查询中使用的ID。
或者,您可以利用Postgress最优秀的数组功能,然后在查询结束时调用一个简单的LIMIT子句:

select
  parent_id, array_agg(age) as children_ages
from child c
where age < 10
group by parent_id
limit 2

(我在这里漏掉了Parent,但显然你可以把它放回原处)。

h22fl7wq

h22fl7wq2#

可以,您可以对SQL连接结果使用GROUP BY子句,就像对单个表中的SELECT一样。然而,与GROUP BY的所有用法一样,输出中不在GROUP子句中的每一列都需要是某个aggregate function的结果。例如,您可以编写

SELECT Parent.id, min(child_age) 
    FROM Parent LEFT JOIN Child ON Parent.id = Child.parent_id 
    WHERE Child.age < 10
    GROUP BY Parent.id; -- Add LIMIT 2 here if you want

让每个父母都有一个年幼的孩子和他们最小的孩子的年龄。
如果您想要的只是子列中的任意值,则可以使用DISTINCT ON(Parent.Id)。例如,

SELECT DISTINCT ON (Parent.id) parent.id, child.id as child_id, child.age as child_age
    FROM Parent LEFT JOIN Child ON Parent.id = Child.parent_id 
    Limit 2;

将为每个父ID提供一行,其中包含该父ID的一些子ID和子年龄。
如果您实际上不需要返回子列,只需在连接中使用它们,那么就不要在选择中包括它们。

相关问题