나는 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<?>
열 유형이 일반 와일드 카드입니다. 몇 가지 솔루션은 여기에 있습니다 :
- 당신이 그것을 필요하지 않은 경우 유형의 안전을 피하십시오. 당신은 항상 당신의 테이블을 선언 할 수 있습니다
Table<?> req_max
. 여기에 모든 종류의 안전을 필요로하는 경우 혼자 예에서, 나는 확실하지 않다 지역 변수와 같은 필드 참조를 추출합니다. 대신 예 내장의
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);