优化子查询和连接

时间:2016-03-17 19:00:41

标签: sql sql-optimization

我有2个表,它们之间可以有多对多的关系:

Person (pid, name, a,b) , 
Attributes (attribId, d,e)

映射存在于单独的表中:

Mapping (mapId, pid, attribId)

目标是获取符合过滤条件的人员的所有人员和属性值。筛选条件基于“属性”表中的列。例如 - 列d。

例如:

Person ->
(1,'person1','a1','b1')
(2,'person2','a1','b1')

Attributes ->
(1,'d1','e1')
(2,'d2','e1')
(3,'d3','e1')
(4,'d3','e2')

Mapping ->
(1,1,1)
(2,1,2)
(3,1,3)

After running the query ->
Result:
(1,'person1','a1','b1')(1,'d1','e1')
(1,'person1','a1','b1')(2,'d2','e1')
(1,'person1','a1','b1')(3,'d3','e1')

查询我一直在尝试 - >

select p.*, a.*
from
    Person p 
left outer join
    Mapping m 
        on p.pid=m.pid 
left outer join
    Attributes a 
        on m.attribId=a.attribId 
where
    p.pid in (select p1.pid
from
    Person p1 
left outer join
    Mapping m1 
        on p1.pid=m1.pid 
left outer join
    Attributes a1
        on m1.attribId=a1.attribId 
where
    a1.d = 'd1')

同样,我还必须丢弃具有特定d值的Person条目。

因此,目前,最终查询如下所示:

SELECT
  p.*,
  a.*
FROM Person p
LEFT OUTER JOIN Mapping m
  ON p.pid = m.pid
LEFT OUTER JOIN Attributes a
  ON m.attribId = a.attribId
WHERE p.pid IN (SELECT
  p1.pid
FROM Person p1
LEFT OUTER JOIN Mapping m1
  ON p1.pid = m1.pid
LEFT OUTER JOIN Attributes a1
  ON m1.attribId = a1.attribId
WHERE a1.d = 'd1')
AND p.pid NOT IN (SELECT
  p2.pid
FROM Person p2
LEFT OUTER JOIN Mapping m2
  ON p2.pid = m2.pid
LEFT OUTER JOIN Attributes a2
  ON m2.attribId = a2.attribId
WHERE a2.d = 'd5');

感觉这个查询效率很低,因为在3个地方完成了相同的连接。有没有办法重用所有子查询的连接并使其更有效?

sqlfiddle demo

3 个答案:

答案 0 :(得分:2)

您可以使用以下方式让所有人满意过滤器:

z{1} to z{4}

您可以使用select m.pid from mapping m join attributes a on m.attribId = a.attribId and a.d = 'dS'; INEXISTS获取所有人/属性组合。哪个更好取决于数据库。但这个想法是:

JOIN

我认为没有理由让这些查询select p.*, a.* from person p join mapping m on p.pid = m.pid join attributes a on m.attribId = a.attribId where p.pid in (select m.pid from mapping m join attributes a on m.attribId = a.attribId and a.d = 'dS' );

编辑:

如果过滤条件基于多个列,则使用left joingroup by作为子查询:

having

答案 1 :(得分:1)

我注意到的第一件事是你在子查询中使用左连接,内连接也可以工作并且速度更快。其次从嵌套选择中删除Person,因为它不需要。

select m2.pid
from
Mapping m2
inner join
    Attributes a2 
        on m2.attribId=a2.attribId 
where
a2.d = 'd5'

答案 2 :(得分:0)

我们也可以做这样的事情

{{1}}

我知道有关于连接与子查询的讨论,但在这种情况下,我认为子查询会更快。