不兼容的类型不允许在 JOOQ dsl 中合并子查询
Posted
技术标签:
【中文标题】不兼容的类型不允许在 JOOQ dsl 中合并子查询【英文标题】:Incompatible type does not allow for union of subqueries in JOOQ dsl 【发布时间】:2019-12-13 10:27:54 【问题描述】:我正在尝试使用 JOOQ 以编程方式在 java 中构建以下查询:
select emisor,
anio,
mes,
sum(case when codigo = '01' then total else 0 end) as facturas,
sum(case when codigo = '03' then total else 0 end) as boletas,
sum(case when codigo = '07' then total else 0 end) as notas_credito,
sum(case when codigo = '08' then total else 0 end) as notas_debito,
sum(case when codigo = 'RC' then total else 0 end) as resumenes,
sum(case when codigo = 'RA' then total else 0 end) as anulaciones,
sum(case when codigo = '40' then total else 0 end) as percepciones,
sum(case when codigo = '20' then total else 0 end) as retenciones,
sum(case when codigo = 'RV' then total else 0 end) as reversiones,
sum(case when codigo = '09' then total else 0 end) as guias
from (select ruc_emisor as emisor,
year(fec_registro) as anio,
month(fec_registro) as mes,
substring(nom_solicitud, 13, 2) as codigo,
count(*) as total
from bd_ose.tx_solicitud
where year(fec_registro) = '2019'
and month(fec_registro) = 7
group by ruc_emisor, anio, mes, codigo
UNION
select num_ruc as emisor,
year(fec_registro) as anio,
month(fec_registro) as mes,
cod_cpe as codigo,
count(*) as total
from bd_ose.tx_comprobante_inf
where year(fec_registro) = '2019'
and month(fec_registro) = 7
group by num_ruc, anio, mes, codigo
) solicitudes
group by emisor, anio, mes
order by emisor;
我在 SQL 和 JOOQ 方面仍然相当缺乏经验,但我决定从内部开始,走出去。当我尝试将 .union() 方法应用于两个内部子查询时,我遇到了问题。我的 IDE 突出显示了一个类型不匹配错误,指出联合需要一个“org.jooq.Select<... .groupby>
我已经检查了 [union docs] (https://www.jooq.org/doc/3.11/manual/sql-building/sql-statements/select-statement/union-clause/) 上的文档,并尝试在其他地方寻找类似的案例,但不幸的是还没有成功。
这是我目前所拥有的:
package pe.net.tci.osereporterservice;
import org.jooq.*;
import org.jooq.impl.DSL;
import org.springframework.stereotype.Repository;
import pe.net.tci.osereporterservice.jooq.tables.TxComprobanteInf;
import pe.net.tci.osereporterservice.jooq.tables.TxSolicitud;
import java.util.List;
@Repository
public class ReportDAO
private final DSLContext dslContext;
TxComprobanteInf txComprobanteInf = TxComprobanteInf.TX_COMPROBANTE_INF;
TxSolicitud txSolicitud = TxSolicitud.TX_SOLICITUD;
public ReportDAO(DSLContext dslContext)
this.dslContext = dslContext;
public List<ReportEntry> produceReport()
Field<Integer> CIanio = DSL.year(txComprobanteInf.FEC_REGISTRO).as("anio");
Field<Integer> CImes = DSL.month(txComprobanteInf.FEC_REGISTRO).as("mes");
Field<?> CIemisor = txComprobanteInf.NUM_RUC.as("emisor");
Field<?> CIcodigo = txComprobanteInf.COD_CPE.as("codigo");
Field<Integer> Sanio = DSL.year(txSolicitud.FEC_REGISTRO).as("anio");
Field<Integer> Smes = DSL.month(txSolicitud.FEC_REGISTRO).as("mes");
Field<?> Semisor = dslContext.select(txSolicitud.RUC_EMISOR.as("emisor");
Field<?> Scodigo = DSL.substring(txSolicitud.NOM_SOLICITUD, 13, 2).as("codigo");
dslContext.select(
Semisor,
Sanio,
Smes,
Scodigo,
DSL.count().as("total")
).from(txSolicitud)
.where(
(DSL.year(txComprobanteInf.FEC_REGISTRO).eq(2019))
.and(DSL.month(txComprobanteInf.FEC_REGISTRO).eq(7))
).union(
dslContext.select(
CIemisor,
CIanio,
CImes,
CIcodigo,
DSL.count().as("total")
).from(txComprobanteInf)
.where(
(CIanio.eq(2019))
.and(CImes.eq(7))
).groupBy(CIemisor, CIanio, CImes, CIcodigo))
//...more code
任何帮助将此 SQL 转换为 JOOQ 或指出与此相关的有用资源将不胜感激。
【问题讨论】:
【参考方案1】:这里的问题是您将一些变量声明为Field<?>
类型,结果Java 编译器没有看到这两个Select
对象是兼容的。所以而不是:
Field<?> CIemisor = txComprobanteInf.NUM_RUC.as("emisor");
Field<?> CIcodigo = txComprobanteInf.COD_CPE.as("codigo");
您应该使用适当的泛型类型参数声明这两个变量。例如
Field<String> CIemisor = txComprobanteInf.NUM_RUC.as("emisor");
Field<String> CIcodigo = txComprobanteInf.COD_CPE.as("codigo");
其他两个变量也是如此。 (我注意到对于变量Semisor
,您需要删除初始化程序中的dslContext.select(
部分。我认为这与您所做的测试有关。)
我认为此更改应该可以解决您的问题。
【讨论】:
以上是关于不兼容的类型不允许在 JOOQ dsl 中合并子查询的主要内容,如果未能解决你的问题,请参考以下文章
使用 JOOQ,为啥要在 insertInto().values() 中使用 DSL.param()?
比较 Querydsl、jOOQ、JEQUEL、activejdbc、iciql 和其他查询 DSL
带有 testcontainers 和 jOOQ 的 Spring Boot 不会注入 DSL 上下文