【问题标题】:QueryDSL - order by count as aliasQueryDSL - 按别名排序
【发布时间】:2016-07-22 08:52:08
【问题描述】:

我正在使用 queryDSL 从数据库中获取一些额外的数据:

public List<Tuple> getUsersWithData (final SomeParam someParam) {
  QUser user = QUser.user;
  QRecord record = QRecord.record;
  JPQLQuery = query = new JPAQuery(getEntityManager());

  NumberPath<Long> cAlias = Expressions.numberPath(Long.class, "cAlias");
  return query.from(user)
       .leftJoin(record).on(record.someParam.eq(someParam))
       .where(user.active.eq(true))
       .groupBy(user)
       .orderBy(cAlias.asc())
       .list(user, record.countDistinct().as(cAlias));
}

尽管它按预期工作,但它会在 SQL 中生成两个 COUNT():

SELECT
  t0.ID
  t0.NAME
  to.ACTIVE
  COUNT(DISTINCT (t1.ID))
FROM USERS t0 LEFT OUTER JOIN t1 ON (t1.SOME_PARAM_ID = ?)
WHERE t0.ACTIVE = true
GROUP BY t0.ID, to.NAME, t0.ACTIVE
ORDER BY COUNT(DISTINCT (t1.ID))

我想知道是否有可能得到这样的东西:

SELECT
  t0.ID
  t0.NAME
  to.ACTIVE
  COUNT(DISTINCT (t1.ID)) as cAlias
FROM USERS t0 LEFT OUTER JOIN t1 ON (t1.SOME_PARAM_ID = ?)
WHERE t0.ACTIVE = true
GROUP BY t0.ID, to.NAME, t0.ACTIVE
ORDER BY cAlias

我无法从文档中理解这一点,如果可能的话,请给我一些指导。

【问题讨论】:

    标签: java postgresql jpa querydsl


    【解决方案1】:
        QVehicle qVehicle = QVehicle.vehicle;
    
        NumberPath<Long> aliasQuantity = Expressions.numberPath(Long.class, "quantity");
        final List<QuantityByTypeVO> quantityByTypeVO = new JPAQueryFactory(getEntityManager())
                .select(Projections.constructor(QuantityByTypeVO.class, qVehicle.tipo, qVehicle.count().as(aliasQuantity)))
                .from(qVehicle)
                .groupBy(qVehicle.type)
                .orderBy(aliasQuantity.desc())
                .fetch();
    
        select 
           vehicleges0_.type as col_0_0_, count(vehicleges0_.pk) as col_1_0_ 
        from vehicle vehicleges0_ 
        group by vehicleges0_.type 
        order by col_1_0_ desc;
    

    我做过类似的事情,但我确实在订购前先数了数。查看查询和生成的选择。

    【讨论】:

    • 您的解决方案非常有效,但存在一个小的依赖问题如果您使用 .select() 从指定字段获取数据并将它们放入我们需要使用 javax 的对象中。注入依赖mvnrepository.com/artifact/javax.inject/javax.inject/1 但是,如果你只想从已经定义的实体中获取数据,没有额外的字段,那么 new JPAQueryFactory(getEntityManager()).from() 就可以了!!
    【解决方案2】:

    这是 SQL 而不是 queryDSL 施加的限制。 您可以尝试在数据库控制台中运行建议的查询 - 我认为它不会执行,至少不会在每个数据库上执行。 但我不认为这个重复的 COUNT() 真的会产生任何性能开销。

    【讨论】:

    • 感谢您的快速回复! Postgres 没问题。我知道这对性能来说并不重要,但这让我很烦恼,我想把事情做对。
    猜你喜欢
    • 2017-12-10
    • 1970-01-01
    • 1970-01-01
    • 2013-07-22
    • 2015-01-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-27
    相关资源
    最近更新 更多