You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Grails GORM Projections中使用sum(case when...)语句?

在Grails GORM Projections中实现SUM(CASE WHEN...)统计

当然可以实现这种自定义聚合统计,但你当前代码里用sqlRestriction的方式是错的——这个方法是用来添加查询条件(比如WHERE/HAVING子句)的,不是用来定义SELECT中的投影字段的。正确的做法是使用sqlProjection方法来定义这个自定义聚合字段。

问题修正与实现步骤

  1. 替换错误的sqlRestriction
    把你代码里的sqlRestriction ("sum(case when status = 0 then 1 else 0 end) waiting_data")替换为sqlProjection,这个方法专门用来在projections中嵌入原生SQL片段:

    sqlProjection("sum(case when status = 0 then 1 else 0 end) as waiting_data", 
                 ["waiting_data"], 
                 [Long.class])
    

    参数说明:

    • 第一个参数:原生SQL片段,必须给统计字段加别名(as waiting_data)
    • 第二个参数:别名列表,和SQL片段里的别名对应
    • 第三个参数:返回类型列表,这里统计数量用Long.class最合适
  2. 清理重复的分组字段
    你代码里重复写了groupProperty("proj.name"),这会导致分组逻辑冗余,需要删掉其中一个。

完整修正后的代码示例

return Product.createCriteria().list() {
    resultTransformer(CriteriaSpecification.ALIAS_TO_ENTITY_MAP)
    // 记得添加关联对象的别名(如果Product和so/acc/proj是关联关系)
    createAlias("so", "so")
    createAlias("acc", "acc")
    createAlias("proj", "proj")
    
    projections {
        count("id")
        property("so.id", "id")
        property("so.soNumber", "soNumber")
        property("so.dateCreated", "dateCreated")
        property("acc.name", "account_name")
        property("proj.name", "project_name")
        property("gtin", "gtin")
        property("status", "status")
        property("statusDate", "status_date")
        
        // 自定义SUM(CASE WHEN...)统计
        sqlProjection("sum(case when status = 0 then 1 else 0 end) as waiting_data", 
                     ["waiting_data"], 
                     [Long.class])
        
        // 分组字段(确保所有非聚合的property字段都在这里)
        groupProperty("so.id")
        groupProperty("so.soNumber")
        groupProperty("so.dateCreated")
        groupProperty("acc.name")
        groupProperty("proj.name")
        groupProperty("gtin")
        groupProperty("status")
        groupProperty("statusDate")
    }
}

额外提示

  • 如果需要统计多个状态的数量,只需添加多个sqlProjection即可,比如统计已处理的数量:
    sqlProjection("sum(case when status = 1 then 1 else 0 end) as processed_data", 
                 ["processed_data"], 
                 [Long.class])
    
  • 确保所有在property中声明的非聚合字段都出现在groupProperty里,否则数据库会抛出分组查询的语法错误(这是SQL的通用规则)

内容的提问来源于stack exchange,提问作者Mister B

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 09:49:03