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

私はそのはコンパイルまたは不明なエラーで実行中に失敗しないか、データ型を定義し、選択図】図(文字列、データ型)を使用して、代わりに「レコード」を使用したが、私はやっているものは何でも含む異なる技術の束を、試してみました。

私は任意の助けのために喜んでいると思います。

ルーカス・エダー:

代わりに、ウィンドウ関数を使用します

一般的に、自己結合はいつでもすることができます避けるべきです。多くの場合、ウィンドウ関数は、ネストされたクエリで集計よりもはるかにエレガントな問題を解決することができます。あなたが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=478593&siteId=1