JPQL Group By not working



这是我的简单JPQL:

SELECT s
FROM Site s
GROUP BY s.siteType
siteResult = q.getResultList();
for (Site site : siteResult) {
    // loops all sites
}

此查询返回所有网站,包括相同网站类型的网站。我使用的是JPA 2.0 Eclipselink。这里怎么了?

这样的查询没有意义。如果使用GROUP BY,则SELECT中的其他属性应该聚合。正如JPA规范中所说:

当使用GROUP BY时,SELECT子句的要求如下SQL的那些:即SELECT子句中出现的任何项(聚合函数或聚合的自变量除外函数)也必须出现在GROUP BY子句中。在形成组中,出于分组目的,空值被视为相同值。

如果您认为SQL对应于您的查询:

SELECT s.attr1, attr2, s.siteType
FROM site s
GROUP BY (s.siteType)

您注意到,很难想象应该选择attr1和attr2的哪个可能值。

在这种情况下,带有derby的EclipseLink只是将GROUP BY从查询中删除,这当然是处理无效JPQL的一种有点可疑的方法。我更喜欢Hibernate+MySQL在这样一个无效的JPQL中的表现,它失败了,错误消息很清楚:

java.sql.SQLSyntaxErrorException:分组查询的SELECT列表至少包含一个无效表达式。如果SELECT列表包含GROUPBY,列表只能包含有效的分组表达式和聚合表达式。

评论答案:一个站点可能也包含siteType以外的属性。让我们使用以下示例:

public class Site {
    int id; 
    String siteType;
} 

和两个实例:(id=1,siteType="same"),(id=2,siteType="same")。现在,当select的类型是Site本身(或它的所有属性),并且您通过siteType进行分组时,不可能定义结果是否具有id值为1或2的结果。这就是为什么您必须使用一些聚合函数(比如AVG,它为您提供属性值的平均值)来处理剩余的属性(在我们的例子中是id)。

在这个链接:ObjectDB GROUP BY后面,您可以找到一些GROUP BY和聚合的示例。

最新更新