Tablas JOOQ derivados

user3567992:

Estoy tratando de expresar lo siguiente SQL en JOOQ. Sin embargo, yo tampoco tengo problemas masivos con tipos que utilizan tablas derivadas o consigo algo que compila pero de cualquier falla en el nivel de SQL o incluso en JAVA. ¿Alguien puede dar una idea de cómo utilizar correctamente las tablas derivadas en este contexto?

SELECT
    id,
    ROUND(num_realized / num_requirements, 2) AS realized_percent,
    ROUND(num_requirements / max_req, 2) AS activity_percent
FROM (
    SELECT
        requirement.project_id AS id,
        COUNT(requirement.id) AS num_requirements,
        COUNT(requirement.realized) AS num_realized
    FROM
        requirement
    GROUP BY
        requirement.project_id) AS stats
    CROSS JOIN (
        SELECT
            MAX(num_requirements) AS max_req
        FROM (
            SELECT
                requirement.project_id AS id,
                COUNT(requirement.id) AS num_requirements,
                COUNT(requirement.realized) AS num_realized
            FROM
                requirement
            GROUP BY
                requirement.project_id) AS stats) AS req_max 

La declaración de bien funciona cuando se aplica en SQL, pero no puedo obtener esta expresión en JOOQ.

Mi último intento fue usar

Table<Record3<Integer, Integer, Integer>> stats =
DSL.select(
    REQUIREMENT.PROJECT_ID.as("id"),
    DSL.count(REQUIREMENT.ID).as("num_requirements"),
    DSL.count(REQUIREMENT.REALIZED).as("num_realized")
).from(REQUIREMENT).groupBy(REQUIREMENT.PROJECT_ID).asTable("stats");

Table<Record2<Integer, Integer>> req_max =
    DSL.select(
        stats.field(0),
        DSL.min(stats.field(1))
    )
    .from(stats).asTable("req_max");

Sin embargo estoy error al obtener: tipos incompatibles:

Table<Record2<CAP#1,CAP#2>> cannot be converted to Table<Record2<Integer,Integer>>

He intentado un montón de diferentes técnicas, incluyendo la definición del tipo de datos y el uso de .field (String, tipo de datos) en lugar de utilizar "registros", pero lo que estoy haciendo, o bien no su compilación o falla durante la ejecución en un error desconocido.

Estaría alegre por cualquier ayuda.

Lukas Eder:

El uso de funciones de la ventana en vez

En general, autocombinaciones debe evitarse siempre que sea posible. En muchos casos, las funciones de la ventana puede resolver un problema mucho más elegante de las agregaciones en consultas anidadas. Si estaba utilizando MySQL 8, la consulta podría ser re-escrita como:

SELECT
    requirement.project_id AS id,
    ROUND(COUNT(requirement.realized) / COUNT(requirement.id), 2) AS realized_percent,
    ROUND(COUNT(requirement.id) / MAX(COUNT(requirement.id)) OVER(), 2) AS activity_percent
FROM
    requirement
GROUP BY
    requirement.project_id    

Note la MAX(..) OVER() función de ventana, que puede agregar funciones de agregación ordinarios como se explica aquí . Sé que estás usando MySQL 5.7, que no tiene el apoyo función de ventana todavía, pero por el bien integridad, esta respuesta necesita una solución basada en función de ventana - tal vez como una motivación para actualizar :-)

Una gran cantidad de consultas complejas jOOQ puede ser más sencilla al hacer la consulta SQL subyacente más simple en el primer lugar.

El problema tabla derivada te encontraste

El problema es el uso de stats.field(0)y stats.field(1). La firma del método es

Field<?> field​(int index)

No hay manera de jOOQ podría ofrecerle la seguridad de tipos cuando se accede a las columnas de una tabla de índice, por lo tanto, el tipo de retorno es Field<?>, donde el tipo de columna es un comodín genérico. Hay algunas soluciones aquí:

  1. Evitar la seguridad de tipos si no lo necesita. Se puede declarar siempre su mesa Table<?> req_max. De su ejemplo solo, no estoy seguro de si necesita cualquier tipo de seguridad aquí
  2. Extraer sus referencias de campo como variables locales. En lugar de incorporar, por ejemplo, la idcolumna de la statstabla, por qué no:

    Field<Integer> id = REQUIREMENT.PROJECT_ID.as("id");
    Field<Integer> numRequirements = DSL.count(REQUIREMENT.ID).as("num_requirements");
    Field<Integer> numRealized = DSL.count(REQUIREMENT.REALIZED).as("num_realized");
    

    y luego utilizar de esta manera:

    var stats =
    DSL.select(id, numRequirements, numRealized)
       .from(REQUIREMENT)
       .groupBy(REQUIREMENT.PROJECT_ID)
       .asTable("stats");
    
    var reqMax =
    DSL.select(stats.field(id), DSL.max(stats.field(numRequirements)))
       .from(stats)
       .asTable(reqMax);
    

Supongo que te gusta

Origin http://10.200.1.11:23101/article/api/json?id=478597&siteId=1
Recomendado
Clasificación