sql >> データベース >  >> RDS >> PostgreSQL

SQLでネストされた関係を簡単かつ効率的に照会するにはどうすればよいですか?

    他のクエリと同様に、最も効率的な方法は「依存する」です。テーブル内の行数、行の長さ、インデックスが存在するかどうか、サーバー上のRAMなど、さまざまな変数が関係しています。

    この種の問題を処理するために私が考えることができる最善の方法(保守性と効率への勇敢なアプローチを考える)は、CTEを使用することです。これにより、一時的な結果を作成し、その結果をクエリ全体で再利用できます。 CTEはWITHキーワードを使用し、基本的に結果をテーブルとしてエイリアス化するため、複数回参加できます。

    WITH user_memberships AS (
        SELECT *
        FROM memberships
        WHERE user_id = ${id}
    ), user_apps AS (
        SELECT *
        FROM apps
        INNER JOIN user_memberships
            ON user_memberships.team_id = apps.team_id
    ), user_collections AS (
        SELECT *
        FROM collections
        INNER JOIN user_memberships
            ON user_memberships.team_id = collections.team_id
    ), user_webhooks AS (
        SELECT *
        FROM webhooks
        LEFT OUTER JOIN user_collections ON user_collections.id = webhooks.collection_id
        INNER JOIN user_memberships
            ON user_memberships.team_id = webhooks.team_id
            OR user_memberships.team_id = user_collections.team_id
    )
    
    SELECT events.* 
    FROM events
    WHERE app_id IN (SELECT id FROM user_apps)
    OR collection_id IN (SELECT id FROM user_collections)
    OR membership_id IN (SELECT id FROM user_memberships)
    OR team_id IN (SELECT team_id FROM user_memberships)
    OR user_id = ${id}
    OR webhook_id IN (SELECT id FROM user_webhooks)
    ;
    

    この方法で行う利点は次のとおりです。

    1. 各CTEは、実行プランナーが一連の複雑な述語を解決しようとするのではなく、適切なJOIN述語のインデックスを利用して、そのサブセットのみの結果をより速く返すことができます。
    2. CTEは個別に保守できるため、サブセットに関する問題のトラブルシューティングが容易になります
    3. DRYの原則に違反していません
    4. CTEにクエリ以外の値がある場合は、それをストアドプロシージャに移動して、代わりにそれを参照できます


    1. SQLite VACUUM

    2. OracleServerで文字列の最初の文字を削除します

    3. MySQLを使用してUnixタイムスタンプを人間が読める形式の日付に変換する

    4. Javaプログラムで呼び出すJavaストアドプロシージャ