JOOQ 파생 테이블

user3567992 :

나는 JOOQ에서 다음 SQL을 표현하기 위해 노력하고있어. 그러나, 나는 중 파생 테이블을 사용하여 유형 엄청난 문제가 아니면 컴파일이 SQL 수준에서 또는 JAVA에 실패하지만 그 중 하나 뭔가를 얻을. 사람이 나에게 이런 맥락에서 제대로 파생 테이블을 사용하는 방법 아이디어를 줄 수 있습니까?

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 

SQL에 적용하지만 JOOQ에이 표현을 얻을 수없는 경우 문은 잘 작동합니다.

내 최신 시도를 사용했다

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");

그러나 나는 오류를 받고 있어요 : 호환되지 않는 유형 :

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

나는 그것의 컴파일 또는 알 수없는 오류로 실행하는 동안 실패하거나하지의 데이터 유형을 정의하고 .field (문자열, 데이터 유형)를 사용하는 대신 "기록"을 사용하지만, 내가 뭘 어떤을 포함하여 다양한 기법의 무리를 시도했다.

나는 어떤 도움을 기꺼이 것입니다.

루카스 에더 :

대신 윈도우 함수를 사용하여

일반적으로, 자기 조인 할 때마다 당신이 할 수 피해야한다. 대부분의 경우, 윈도우 함수는 중첩 된 쿼리의 집계보다 훨씬 더 우아하게 문제를 해결할 수 있습니다. 당신은 MySQL의 8을 사용한 경우, 쿼리는 다음과 같이 다시 쓸 수있다 :

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    

통지 MAX(..) OVER() 여기에 설명 된대로 일반 집계 함수를 집계 할 수 윈도우 함수를 . 난 당신이 더 윈도우 기능 지원을 아직 없습니다 MySQL은 5.7을 사용하고 있습니다 알고 있지만, 완전성 '을 위해,이 대답은 윈도우 함수 기반 솔루션을 필요로 - 어쩌면 업그레이드 할 동기 부여로 :-)

복잡한 jOOQ 쿼리의 많은 처음에 간단한 기본 SQL 쿼리를함으로써 간단하게 만들 수 있습니다.

당신이 우연히 파생 테이블 문제

문제는 당신의 사용이다 stats.field(0)stats.field(1). 메소드 서명은

Field<?> field​(int index)

당신은 인덱스 테이블의 열을 액세스 할 때 jOOQ 유형의 안전을 제공 할 수있는 방법은 따라서 반환 유형이, 없다 Field<?>열 유형이 일반 와일드 카드입니다. 몇 가지 솔루션은 여기에 있습니다 :

  1. 당신이 그것을 필요하지 않은 경우 유형의 안전을 피하십시오. 당신은 항상 당신의 테이블을 선언 할 수 있습니다 Table<?> req_max. 여기에 모든 종류의 안전을 필요로하는 경우 혼자 예에서, 나는 확실하지 않다
  2. 지역 변수와 같은 필드 참조를 추출합니다. 대신 예 내장의 id당신에 열을 stats테이블, 왜 안 :

    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");
    

    다음과 같이 사용 :

    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);
    

추천

출처http://10.200.1.11:23101/article/api/json?id=478590&siteId=1