2016-12-07 9 views
0

以下は、3つのテーブルを持つスキーマの例です。すべての子シフトのステータスが6であるすべてのジョブを返すクエリを実行しようとしています。ジョブのステータスが5の子Shiftがある場合、ジョブは返されません。以下に挿入されたサンプルデータからのクエリに対する適切な応答は返されません。PostgreSQLサブクエリをジョインに変換する

コメント「Works」の下に動作するクエリがあります。サブクエリの代わりにジョインを使用するために、 "works"クエリをリファクタリングしようとしています。コメントが「動作しません」というクエリは私の試みです。

-- begin setup and table creation: only run this section once. 

CREATE EXTENSION "uuid-ossp"; 

CREATE TABLE jobs 
(
    id uuid NOT NULL DEFAULT uuid_generate_v4(), 
    CONSTRAINT jobs_pkey PRIMARY KEY (id) 
); 

CREATE TABLE bookings 
(
    id uuid NOT NULL DEFAULT uuid_generate_v4(), 
    job_id uuid, 
    CONSTRAINT bookings_pkey PRIMARY KEY (id) 
); 

CREATE TABLE shifts 
(
    id uuid NOT NULL DEFAULT uuid_generate_v4(), 
    booking_id uuid, 
    status integer, 
    CONSTRAINT shifts_pkey PRIMARY KEY (id) 
); 

insert into jobs (id) values ('e857c86c-bc31-11e6-9aae-57793f585d49'); 

insert into bookings (id, job_id) values ('736da82c-bc32-11e6-b9b8-f36753d321ac', 'e857c86c-bc31-11e6-9aae-57793f585d49'); 
insert into bookings (id, job_id) values ('7d839e5c-bc32-11e6-8bb3-4fa95be86a74', 'e857c86c-bc31-11e6-9aae-57793f585d49'); 

insert into shifts (booking_id, status) values ('736da82c-bc32-11e6-b9b8-f36753d321ac', 6); 
insert into shifts (booking_id, status) values ('7d839e5c-bc32-11e6-8bb3-4fa95be86a74', 5); 

-- end setup and table creation 

私たちは、ジョブが5の状態を持つ子シフトを持っている場合、すべての子のシフトが状態6であるすべてのジョブをしたい、ジョブが返されるべきではありません。上に挿入されたサンプル・データからの問合せに対する適切な応答は、戻される行はありません。

は動作しません:(

SELECT "jobs".* 
FROM "jobs" 
    inner join bookings b1 on jobs.id = b1.job_id 
    inner join shifts s1 on b1.id = s1.booking_id 
    left outer join bookings b2 on jobs.id = b2.job_id 
    left outer join shifts s2 on b2.id = s2.booking_id and s2.status IN (2,3,4,5) 
WHERE s1.status = 6 
    AND s2.id IS NULL 
GROUP BY "jobs"."id"; 

作品

SELECT "jobs".* 
FROM "jobs" 
WHERE jobs.id IN (
    SELECT job_id 
    FROM bookings 
    WHERE bookings.id IN (
     SELECT booking_id FROM shifts WHERE status = 6 
    ) 
) AND jobs.id NOT IN (
    SELECT job_id FROM bookings WHERE bookings.id IN (
     SELECT booking_id FROM shifts WHERE status IN (2,3,4,5) 
    ) 
) 
GROUP BY "jobs"."id"; 

がどのように私は「作品」を使用するクエリは、クエリが私の試みである「動作しない」?代わりにサブクエリの加入をリファクタリングすることができます。

+1

サブクエリアプローチの問題点は何ですか?サブクエリは相関関係にあるようには見えないため、パフォーマンスの観点からは大きな問題ではないかもしれません。 –

+0

結合が必ずしもサブクエリ解と同じ結果を返すとは限りません。では、なぜそれを書き直したいのですか? –

+0

あなたはおそらく、サブクエリがほとんど常に結合よりも遅いmysqlバックグラウンドから来ているでしょう。 postgresqlではそうではありません。 **あなたはこれをする必要はありません** – e4c5

答えて

0

(タイプミスがあるかもしれないので、テストしていない)、これを試してみてください:

with prohibited_jobs as (
    select distinct jobs.id 
    from jobs 
     join bookings on jobs.id == bookings.job_id 
     join shifts on shifts.booking_id = booking.job_id 
    where shift.status != 6 
) 
select jobs.* 
from jobs 
    left outer join prohibited_jobs p on p.id = jobs.id 
where 
    p.id IS NULL 

サブクエリから完全に解放されているわけではありません(ジョインですべてのことを行うのが最も効率的ではありません)が、不要なチェックがいくつか削除されるため、少し速くなる可能性があります。

すべてのシフトがステータス6であるすべてのジョブを返すという点で、クエリには少しの違いがありますが、クエリでは少なくとも1つのシフト(ステータス6)。

関連する問題