【问题标题】:Blaze-Persistence GROUP BY in LEFT JOIN SUBQUERY with COALESCE in root queryLEFT JOIN SUBQUERY 中的 Blaze-Persistence GROUP BY 与根查询中的 COALESCE
【发布时间】:2021-03-06 23:57:30
【问题描述】:

我需要有关按代码标记的警报的统计信息。具有基于组的限制的用户可以看到警报。如果某些标签代码仅在用户不可见的警报中,则应在统计信息中显示 0。

表格结构:

┌─────────────────┐      ┌───────────┐     ┌─────┐
│ ALERT           │      │ ALERT_TAG │     │TAG  │
│ id              ├──────┤ alertId   ├─────┤code │
│ finalized       │      │ tag_code  │     └─────┘
│ assigneeGroupId │      └───────────┘
└─────────────────┘

我正在使用 Blaze-Persistence 并尝试在根查询中使用 LEFT JOIN SUBQUERY 中的 GROUP BYCOALESCE。使用 Blaze-Persistence 的原因是支持左连接中的子查询。

这是我的代码:

criteriaBuilderFactory.create(entityManager, javax.persistence.Tuple.class)
            .from(Tag.class)
            .select("code")
            .select("COALESCE(at.tagCount, 0)")
            .leftJoinOnSubquery(AlertTagCTE.class, "at")
            .from(AlertTag.class)
            .bind("tagCode").select("tag.code")
            .bind("tagCount").select("count(tag.code)")
            .join("alert", "a", JoinType.INNER)
            .where("a.finalized").eq(false)
            .where("a.assigneeGroupId").in(userGroups)
            .groupBy("tag.code")
            .end()
            .end()
            .getQuery()
            .getResultList();
@Entity
@CTE
public class AlertTagCTE {

  @Id private String tagCode;
  private Long tagCount;

}

在执行期间我希望得到这个查询:

select t.code, nvl(atj.tag_count, 0) 
from tag t
left join (
    select alert_tag.tag_code, count(alert_tag.tag_code) as tag_count 
    from alert_tag 
    join alert ata 
    ON alert_tag.alert_id = ata.id 
    WHERE
        ata.finalized = 0 
        AND ata.assignee_group_id in (37 , 38 , 39 , 44 , 12 , 14 , 18 , 19 , 20 , 22 , 23 , 25 , 26 , 30) 
    group by alert_tag.tag_code
) atj on t.code = atj.tag_code
order by t.code;

但我得到了这个:

sqlselect tag0_.code as col_0_0_, nvl(alerttagct1_.tag_count, 0) as col_1_0_ 
from tag tag0_ 
left outer join (
    select null tag_code,null tag_count from dual where 1=0 union all (
        select alerttag0_.tag_code as col_0_0_, count(alerttag0_.tag_code) as col_1_0_ 
        from alert_tag alerttag0_ 
        inner join alert alert1_ on alerttag0_.alert_id=alert1_.id 
        where 
        alert1_.finalized=false 
        and (alert1_.assignee_group_id in (37 , 38 , 39 , 44 , 12 , 14 , 18 , 19 , 20 , 22 , 23 , 25 , 26 , 30)) 
        group by alerttag0_.tag_code
    )
) alerttagct1_ on ((null is null));

两个查询的结果不同。

  1. 为什么会出现这个联合?
  2. 是否可以在 Blaze 持久性 API 中获取没有联合的查询?

【问题讨论】:

    标签: java sql hibernate jpa blaze-persistence


    【解决方案1】:

    您在查询构建器中缺少您的条件:

    criteriaBuilderFactory.create(entityManager, javax.persistence.Tuple.class)
            .from(Tag.class)
            .select("code")
            .select("COALESCE(at.tagCount, 0)")
            .leftJoinOnSubquery(AlertTagCTE.class, "at")
                .from(AlertTag.class)
                .bind("tagCode").select("tag.code")
                .bind("tagCount").select("count(tag.code)")
                .join("alert", "a", JoinType.INNER)
                .where("a.finalized").eqLiteral(false)
                .where("a.assigneeGroupId").in(userGroups)
                .groupBy("tag.code")
            .end()
                .on("at.tagCode").eqExpression("t.code") // This was missing
            .end()
            .getQuery()
            .getResultList();
    

    联合只是用于命名列,但它不应该是一个问题,因为它不会产生结果,优化器应该能够优化它。你觉得这有什么问题吗?这样做的主要原因是,命名子查询的项目将需要尽可能避免的 SQL 的解析和调整。

    数据库,例如PostgreSQL 支持在表别名后使用别名。显然您正在使用不支持此功能的数据库,例如甲骨文还是 MySQL?

    【讨论】:

    • 我的实现中的愚蠢错误导致更好地了解 Blaze API 及其工作原理。添加条款解决了这个问题。经过你的解释,工会没有任何问题。你是对的,我在 Oracle DB 上运行。谢谢@Christian Beikov。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-01
    • 1970-01-01
    • 2021-11-06
    • 2015-08-21
    • 1970-01-01
    相关资源
    最近更新 更多