JPA/Criteria builder 使用 DATEDIFF 函数到 SUM 聚合函数中

问题描述

使用标准 api,我有一个查询,它执行以下操作:

    CriteriaBuilder cb = getCriteriaBuilder();
    CriteriaQuery<BranchPhoneAnswerRateReportResult> cq = cb.createquery(BranchPhoneAnswerRateReportResult.class);
    Root<BasicServiceCdr> root = cq.from(BasicServiceCdr.class);
    List<Predicate> listPredicate = new ArrayList<>();
    Join<BasicServiceCdr,BranchPhoneAnswerRateReportResult> joinXfer = root.join("xferResultType",JoinType.LEFT);
    Join<BasicServiceCdr,BranchPhoneAnswerRateReportResult> joinService = root.join("service",JoinType.LEFT);

     Expression<String> second = new UnitExpression(null,String.class,"SECOND");
     Expression<Integer> timeDiff = cb.function(
                "DATEDIFF",Integer.class,second,root.<Date>get("callEndTime"),root.<Date>get("callStartTime"));

     Predicate timeDiffPredicate =  cb.lessthanorEqualTo(timeDiff,3);
     Predicate shortCallXferPredicate = cb.equal(joinXfer.get("name"),"Success");
        

    cq.select(cb.construct(BranchPhoneAnswerRateReportResult.class,joinService.get("serviceName").alias("branchName")
            //joinService.get("").alias("succesCallRate"),// this will be rate,cb.sum(cb.selectCase(joinXfer.get("name")).when("Success",1).otherwise(0).as(Long.class))
                    .alias("successCallCount"),cb.sum(cb.selectCase(joinXfer.get("name")).when("NoA",1).otherwise(0).as(Long.class)).alias("missedCallCount"),cb.sum(cb.selectCase(joinXfer.get("name")).when("Busy",1).otherwise(0).as(Long.class)).alias("busyCallCount"),cb.sum(cb.selectCase(joinXfer.get("name")).when("Failed",1).when("PlayIntro",1).when("PlayMenu",1).otherwise(0)
                    .as(Long.class)).alias("unRealizedCallCount"),cb.sum(cb.selectCase()
                    .when(cb.and(shortCallXferPredicate,timeDiffPredicate),1).otherwise(0)
                    .as(Long.class)).alias("shortCallCount"),cb.sum(cb.selectCase(joinXfer.get("name")).when("XferStarted",1).otherwise(0).as(Long.class)).alias("xferStartedCallCount")
            ));
    
    Predicate startDatePredicate = cb.greaterThanorEqualTo(root.get("callStartTime"),branchPhoneAnswerRateReportDTO.getStartTime());
    Predicate endDatePredicate = cb.lessthan(root.get("callStartTime"),branchPhoneAnswerRateReportDTO.getEndTime());
    listPredicate.add(startDatePredicate);
    listPredicate.add(endDatePredicate);
    cq.groupBy(joinService.get("serviceName"));
    
    cq.where(cb.and(listPredicate.toArray(new Predicate[] {})));

    TypedQuery<BranchPhoneAnswerRateReportResult> query = getEntityManager().createquery(cq);
    query.setFirstResult(Long.valueOf(pageable.getoffset()).intValue());
    return query.getResultList();

运行上述查询时,出现如下错误

    CAST function should only have 2 arguments [

select new com.defne.entities.concrete.reports.BranchPhoneAnswerRateReportResult(
generatedalias0.serviceName,sum(cast(case generatedalias1.name when 'Success' then 1 else 0 end as long)),sum(cast(case generatedalias1.name when 'NoA' then 1 else 0 end as long)),sum(cast(case generatedalias1.name when 'Busy' then 1 else 0 end as long)),sum(cast(case generatedalias1.name when 'Failed' then 1 when 'PlayIntro' then 1 when 'PlayMenu' then 1 else 0 end as long)),sum(cast(case when ( generatedalias1.name='Success' ) and ( function('DATEDIFF',SECOND,generatedalias2.callEndTime,generatedalias2.callStartTime)<=3 ) then 1 else 0 end as long)),sum(cast(case generatedalias1.name when 'XferStarted' then 1 else 0 end as long))) from com.defne.entities.concrete.BasicServiceCdr as generatedalias2 
left join generatedalias2.xferResultType as generatedalias1 
left join generatedalias2.service as generatedalias0 where 
( generatedalias2.callStartTime>=:param0 ) and ( generatedalias2.callStartTime<:param1 ) group by generatedalias0.serviceName

]

删除此行后一切正常:

,1).otherwise(0)

当我删除使用 Datediff 的行时,一切正常。我转发下面的查询结果。

    select
    service2_.service_name as col_0_0_,sum(cast(case xferresult1_.name 
        when 'Success' then 1 
        else 0 
    end as bigint)) as col_1_0_,sum(cast(case xferresult1_.name 
        when 'NoA' then 1 
        else 0 
    end as bigint)) as col_2_0_,sum(cast(case xferresult1_.name 
        when 'Busy' then 1 
        else 0 
    end as bigint)) as col_3_0_,sum(cast(case xferresult1_.name 
        when 'Failed' then 1 
        when 'PlayIntro' then 1 
        when 'PlayMenu' then 1 
        else 0 
    end as bigint)) as col_4_0_,sum(cast(case xferresult1_.name 
        when 'XferStarted' then 1 
        else 0 
    end as bigint)) as col_5_0_ 
from
    basic_service_cdr basicservi0_ 
left outer join
    xfer_result_type xferresult1_ 
        on basicservi0_.xfer_result_type=xferresult1_.id 
left outer join
    service service2_ 
        on basicservi0_.service_id=service2_.id 
where
    basicservi0_.call_start_time>=? 
    and basicservi0_.call_start_time<? 
group by
    service2_.service_name

最后,我的问题。如何使用 Datediff 运行查询

为什么我使用Datediff函数时需要强制转换?

先谢谢大家。

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)