【问题标题】:Java Spring JPA: How to find the sum of only non null values in a column?Java Spring JPA:如何查找列中仅非空值的总和?
【发布时间】:2021-09-09 21:48:23
【问题描述】:

我目前有这样的查询:

SELECT DISTINCT t.column1, SUM(t2.column2 IS NOT NULL)
FROM table t
LEFT OUTER JOIN table t2 on table.id = t2.id
GROUP BY column1, column2;

我正在尝试使用 Spring JPA CriteriaBuilder 实现查询。我看到 CriteriaBuilder.sum() 方法,但我没有看到将 IS NOT NULL 部分应用于选择的方法。 Column2的数据类型是字符串。

我的代码示例

criteriaBuilder.multiselect(root.get("column1"), cb.sum(root.get("column2")));

【问题讨论】:

  • 为什么不在 WHERE 子句中加入“t2.column2 IS NOT NULL”?
  • 如何对字符串类型求和?
  • GROUP BY column1, column2 看起来也不对。
  • 它对非空记录的数量求和 @Bohemian 查询在 MYSQL 中按预期工作。
  • @mvmn 如果我在 WHERE 子句中添加“t2.column2 IS NOT NULL”,左外连接将无法按预期工作。在右表中添加 WHERE 子句会导致左外连接被取消。

标签: java mysql spring-data-jpa


【解决方案1】:

我能够找到解决问题的方法。感谢@bohemian 帮助我编写了正确的求和表达式。

 final CriteriaBuilder cb = em.getCriteriaBuilder();
 final CriteriaQuery<Model1> cq = cb.createQuery(Model1.class);
 final Root<Model1> root = cq.from(Model1.class);
 final Join<Model1, Model1> selfJoin = 
     root.join("tableJoinColumn", JoinType.LEFT);
selfJoin.on(...);
cq.multiselect(root.get("column1"), cb.sum(cb.selectCase()
    .when(cb.isNull(selfJoin.get("column2")), 0).otherwise(1).as(Long.class)));
...

自联接要求我在我的模型上创建一个附加属性。 Model1.java

    /**
     * Property for LEFT INNER JOIN.
     */
    @OneToOne(fetch = FetchType.LAZY)
    @JoinColumn(name="id")
    private Model1 tableJoinColumn;

How to use JPA CriteriaBuilder selectCase() so that it can have Predicate as result?

Self join in criteria query

【讨论】:

    【解决方案2】:

    只有在 MySQL 中才会运行这样的查询,因为 MySQL 的语法规则比较宽松。

    特别是在mysql中sum(column2 is not null)是一个count,而不是一个sum。表达式column2 is not null 是布尔值,在 mysql 中 false 为 0,true 为 1,因此将此表达式求和是 mysql hack,用于计算 column2 不为空的次数。

    将其转换为标准 sql:

    select
        t.column1,
        count(t2.column2)
    from table t
    left join table t2 on t.id = t2.id
    group by t.column1
    

    这是因为count()(和所有聚合函数)忽略空值。

    此版本还更正了 group by 子句中的错误列 - 在任何其他数据库中,您的查询会产生“按聚合表达式分组”错误。

    此查询将在 MySQL 中产生与您当前查询相同的结果。

    【讨论】:

    • 那么查询在MYSQL中是如何按预期工作的呢?在MYSQL中,SUM(column2 is not null) 将column2中非空记录的数量相加。
    • @MatthewS。在 mysql 中,SUM(column2 is not null)count,而不是 sum。表达式 column2 is not null 是布尔值,在 mysql 中 false 为 0,true 为 1,因此将此表达式求和是一个 mysql hack,以 countcolumn2 不为空。非黑客和可移植的方式是sum(case when column2 is null then 0 else 1 end)。这是否有意义并解决了您的问题?
    • 这是有道理的,但这并不能解决我尝试将 MYSQL 查询转换为可用于 Criteria Builder 的内容的问题。
    猜你喜欢
    • 2017-12-03
    • 2020-10-13
    • 1970-01-01
    • 2018-11-10
    • 1970-01-01
    • 1970-01-01
    • 2021-10-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多