【问题标题】:Grails: "Not in aggregate function" problem with HQL queryGrails:HQL 查询的“不在聚合函数中”问题
【发布时间】:2011-07-26 15:41:20
【问题描述】:

HQL 查询

select a from Article a join a.tags t 
where t.name in (:tags) 
group by a 
having count(t)=:tag_count

在 Grails 中使用 HSQLDB 会产生 SqlException“不在聚合函数中...”。查看生成的 SQL 提供

SELECT a.id, a.title, a.url, ....
..
GROUP BY a.id
HAVING ..

我听说在某些 MySQL 产品中可以这样做,但在 HSQLDB 中显然不行。我不明白:

  1. 为什么 Hibernate 会生成错误的 SQL?还是没有?
  2. 为什么 HSQLDB 在选择批次时不允许对 id 进行分组,我的意思是它毕竟是主键,而且我的 SELECT 不会引入不确定值,例如随机或当前时间

【问题讨论】:

    标签: hibernate grails hql hsqldb


    【解决方案1】:

    生成的 SQL 不太正确,因为我们应该在 SELECT 子句中对所有非聚合属性进行 GROUPBY。例如:

    SELECT name,category FROM books
    GROUP BY category;
    

    上面的查询会给出错误的数据,因为它只会给出一个类别的 1 行(即使在 MySQL 中运行)。相反,应该这样做:

    SELECT name,category FROM books
    GROUP BY name,category;
    

    编辑:经过进一步调查,我意识到 MySQL 是不遵守规则的。为了查询优化,MySQL 不允许不完整的 GROUP BY 查询(默认情况下,有一个选项可以关闭此功能)。如果在 Oracle 或 HSQLDB 等其他数据库上运行查询,则会出现错误。详细答案见this question

    EDIT2:要按照您的方式重写查询,除了在Group By 子句中列出所有非聚合选择的属性外,没有其他方法。来自Hibernate doc

    Hibernate 目前也没有 展开一个分组的实体,所以你不能 如果所有属性都按 cat 分组 的 cat 是非聚合的。你必须 列出所有非聚合属性 明确的。

    @Tom:但我认为您可能不需要 Article 表中的所有字段。如果是这种情况,您是否介意提供有关域类以及您要查询的内容的更多信息,以便我们更清楚地看到问题?

    【讨论】:

    • 好的,干杯,但我不太担心理解 MySQL,而是担心如何让 Hibernate 在我的 Grails/HQL 应用程序中正常工作,或者如果它是一个 DataSource/HSQLDB 配置的东西。跨度>
    • @Tom:所以你想让 Hibernate 生成有效的 SQL 查询?不知道HSQLDB有没有选项可以放开这个选项,不过可以改查询
    • @Tom:我认为有一个解决方法:您可以先在 groupBy 查询中选择 a.id,然后使用这些 id 再次重新查询。也许有更好的方法使用标准,但我不熟悉你的域。你能提供更多细节吗?
    • 是的,这可以解决问题。你知道如何重写我上面的问题中的 HQL 以这样工作吗?
    【解决方案2】:

    刚刚在 Hibernate 问题跟踪器中找到 this bug。看来这是一个已经存在了五年的已知问题......难以置信。看到看似基本的东西可以被破坏这么长时间,这总是令人惊讶。

    【讨论】:

      【解决方案3】:

      只要 ID 是主键列,当前的 SQL 标准实际上允许这种类型的查询。但这被认为是标准的可选功能,不需要数据库引擎支持。

      当 ID 是主键列时,HSQLDB 2.x 支持这一点。

      【讨论】:

        猜你喜欢
        • 2011-04-08
        • 1970-01-01
        • 1970-01-01
        • 2021-12-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多