下面是一个包含3个表的示例模式。我正在尝试运行一个查询,返回所有子移位状态为6的所有作业。如果作业有一个状态为5的子Shift,则不应返回作业。从下面插入的示例数据中查询的正确响应是没有返回任何行。
下面有一个工作查询,注释“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
我们希望所有子女轮班的所有工作都处于状态6.如果某个工作的子班次状态为5,则不应该返回该工作。来自上面插入的样本数据的查询的正确响应是没有返回任何行。
不起作用:(
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";
如何重构“works”查询以使用连接而不是子查询? “无效”查询是我的尝试。
答案 0 :(得分: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
它没有完全摆脱子查询(使用连接做任何事情肯定会效率低下),但它会删除一些不必要的检查,因此可能会更快一点(我怀疑这是你的目标)。 / p>
您的工作查询存在细微差别,因为它返回所有班次都具有状态6的所有作业(如您所说),而您的查询还确保作业至少有一个班次(状态为6) )。