【问题标题】:How to deal with null values - JPA/SQL/JPQL如何处理空值 - JPA/SQL/JPQL
【发布时间】:2014-04-20 15:37:15
【问题描述】:

应该很简单,但我目前真的很困惑

我有一个数据库查询:

   public double markingAvg(Marking id) {
        System.out.println("In MarkingAvg");
        System.out.println("id = " + id);
        System.out.println("id = " + id.getId());
        Query m = em.createQuery("SELECT m.markSectionOne, m.markSectionTwo, m.markSectionThree, m.markSectionFour, m.markSectionFive, m.markSectionSix, m.markSectionSeven, m.markSectionEight, m.markSectionNine, m.markSectionTen, m.markSectionEleven, m.markSectionTwelve, m.markSectionThirteen FROM MARKING m WHERE m.id = :id", Double.class);
        m.setParameter("id", id.getId()); // Note the getId()
        System.out.println(m);


        List<Object[]> allMarks = m.getResultList();
        double total = 0.0;
        int count = 0;

        for (Object[] marks : allMarks) {
            for (Object mark : marks) {
                total += Double.parseDouble((String) mark);
                ++count;
            }
        }
        return total / (double) count;
    }

它只是从 13 列中获取值并对它们进行平均,但是当它们中有空值时它会中断,有没有办法说是否有任何列中的空值要返回总数为0?谢谢

【问题讨论】:

  • 您的意思是,如果列的值为 NULL,则应将其评估为 0,或者一旦其中一列为 NULL,您希望总数等于 0?
  • 理想情况下,如果一列为 NULL,则应将其评估为 0,但是一旦单列为空,总计 = 0 也是可以接受的

标签: sql jpa derby jpql


【解决方案1】:

您可以为此使用内联条件检查:

    total += Double.parseDouble((String) ((mark==null) ? 0 : mark)));

【讨论】:

  • 我收到错误 java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String 但这看起来像是我想要的解决方案
  • total += Double.parseDouble((String) ((mark == null) ? "0" : mark));
  • 我的错,我没有考虑数据类型转换。 String.valueOf(((mark == null) ? 0 : mark)) 应该可以工作。或者,正如您已经知道的那样,双引号应该可以工作
【解决方案2】:

您也可以在查询中处理此问题:例如:

ij> CREATE TABLE T(I INT);
ij> INSERT INTO T VALUES 1, 2, 3, NULL;
4 rows inserted/updated/deleted
ij> SELECT * FROM T;
I          
-----------
1          
2          
3          
NULL       

4 rows selected
ij> SELECT (CASE WHEN I IS NULL THEN 0 ELSE I END) FROM T;
1          
-----------
1          
2          
3          
0          

4 rows selected

在您的情况下,用 SQL 计算平均值可能会更好

ij> SELECT AVG(CAST(I AS DOUBLE)) AS AVERAGE FROM T;
AVERAGE                 
------------------------
2.0                     
WARNING 01003: Null values were eliminated from the argument of a column function.

1 row selected

注意警告。如果您真的希望 NULL 在平均值中计为 0,则必须使用上面提到的 CASE 表达式。

【讨论】:

    【解决方案3】:

    将您的查询更改为以下内容:

    SELECT NVL(m.markSectionOne,0), 
           NVL(m.markSectionTwo,0), 
           NVL(m.markSectionThree,0), 
           NVL(m.markSectionFour,0), 
           NVL(m.markSectionFive,0), 
           NVL(m.markSectionSix,0), 
           NVL(m.markSectionSeven,0),
           NVL(m.markSectionEight,0),
           NVL(m.markSectionNine,0), 
           NVL(m.markSectionTen,0),
           NVL(m.markSectionEleven,0), 
           NVL(m.markSectionTwelve,0),
           NVL(m.markSectionThirteen,0) 
    FROM MARKING m WHERE m.id = :id;
    

    【讨论】:

      猜你喜欢
      • 2012-11-23
      • 1970-01-01
      • 2013-07-15
      • 2015-02-09
      • 2018-03-19
      • 2017-08-30
      • 2014-02-21
      • 2015-03-28
      • 2012-12-29
      相关资源
      最近更新 更多