我有两个表table1
和table2
。 table2
包含table1
中记录的权限,即e。 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(请参见下文)。
如何减少此查询的费用?
答案 0 :(得分:1)
您在存在子句上有一个相关子查询作为谓词,该子查询针对每个过滤的父行执行。尝试这个。 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
);