我有两张桌子,table1
和table2
。 table2
包含table1
记录的权限,i。即table1
中的一行可以在table2
中有多个相应的行。
现在我需要编写一个SQL语句来检索那些table1
记录
table1.ID
)和我提出了这个问题:
SELECT table1.id
FROM TABLE1 table1
WHERE table1.ID IN (<ID_List>) AND
(<Excluded_permission_List>) NOT IN (
Select PERMISSION_NAME
from TABLE2 table2
where table2.perm_owner_id = table1.id
);
哪里
<ID_List>
是要搜索的所有table1主键的列表,和<Excluded_permission_List>
所有被排除权限的列表(即,如果table1
记录具有<Excluded_permission_List>
中包含的任何权限,则不应出现在结果中)。例:
SELECT table1.id
FROM TABLE1 table1
WHERE table1.ID IN (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12) AND
('SUPERUSER-1', 'MODERATOR-2') NOT IN (
Select PERMISSION_NAME
from TABLE2 table2
where table2.perm_owner_id = table1.id
);
该查询应该返回那些table1记录,其中
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12
和SUPERUSER-1
,也没有MODERATOR-2
。此查询有效,但根据EXPLAIN PLAN
,成本为38(见下文)。
如何降低此查询的成本?
您在exists子句上有一个相关子查询作为谓词,它对每个已过滤的父行执行。试试这个。 CBO可以将谓词重写为反连接(散列连接或嵌套循环)
SELECT table1.id
FROM TABLE1 table1
WHERE table1.ID IN (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12) AND
(('SUPERUSER-1', table1.id), ('MODERATOR-2', table1.id)) NOT IN (
select table2.permission_name, table2.perm_owner_id
from TABLE2 table2
where table2.perm_owner_id is not null and table2.permission_name is not null
);