内部连接 3 个或更多表如何工作?
How does Inner join 3 or more tables works?
我看到了一些关于这个主题的问题,但坦白说我不太明白。
我想要什么:我有五个 table,我想 return 一个 select 与主要 table 与其他 4 个的所有交叉点。我我目前正在做 2 selects,然后是 UNION。它工作得很好,但我想我可以在单个 select.
中提高性能
这是我的代码示例:
SELECT column1 FROM tableA A
INNER JOIN table B ON A.column1 = B.column1
LEFT JOIN table D ON A.column1 = D.column1
LEFT JOIN table E A.column1 = E.column1
WHERE B.column2 IS NOT NULL
AND B.column3 = '7'
AND ( (D.column2 = 'x' OR D.column3 = 'y') OR (E.column2 = 'x' OR E.column3 = 'y') )
UNION
SELECT column1 FROM tableA A
INNER JOIN table C ON A.column1 = C.column1
LEFT JOIN table D ON A.column1 = D.column1
LEFT JOIN table E A.column1 = E.column1
WHERE C.column2 IS NOT NULL
AND C.column3 = '7'
AND ( (D.otherColumn2= 'x' OR D.otherColumn3 = 'y') OR (E.otherColumn2 = 'x' OR E.otherColumn3 = 'y') )
关于 tables.
Table A 与所有其他 table 共享 column1
:
(int) column1
Tables B和C结构相同如下:
(int) column1 | (int) column2 | (varchar) column3
和tables D和E也有相同的结构:
(int) column1 | (varchar) otherColumn2 | (varchar) otherColumn3
正如我们所见,两个 select 几乎相同,除了 table B 和 C.
我在没有完整代码的情况下问了这个问题,@Kevin 解决了它。但是有了这些额外的信息,并尝试按照他的例子,我将代码更改为:
SELECT column1 FROM tableA A
LEFT JOIN table B ON (A.column1 = B.column1
AND C.column2 IS NOT NULL
AND C.column3 = '7')
LEFT JOIN table C ON (A.column1 = C.column1
AND C.column2 IS NOT NULL
AND C.column3 = '7')
LEFT JOIN table D ON A.column1 = D.column1
AND (D.otherColumn2 = 'x' OR D.otherColumn3 = 'y')
LEFT JOIN table E A.column1 = E.column1
AND (E.otherColumn2 = 'x' OR E.otherColumn3 = 'y')
WHERE
B.column1 is not null
or c.column1 is not null
or D.column1 is not null
or E.column1 is not null
但是我得到了很多额外的结果。我希望我在这里说清楚了,如果没有,请告诉我,我会更新这个问题。
这应该可以满足您的需求。不过,我不知道性能会好到什么地步。
SELECT A.column1 FROM tableA A
LEFT JOIN tableB B ON A.column1 = B.column1
AND B.column2 IS NOT NULL
AND B.column3 = '7'
LEFT JOIN tableD d ON b.column1 = D.column1
LEFT JOIN tableE e ON B.column1 = E.column1
LEFT JOIN tableC C ON A.column1 = C.column1
AND C.column2 IS NOT NULL
AND C.column3 = '7'
LEFT JOIN tableD d2 ON c.column1 = d2.column1
LEFT JOIN tableE e2 ON c.column1 = e2.column1
WHERE (B.column1 is not null
and (d.othercolumn2 = 'x' or d.othercolumn3='y' or e.othercolumn2 = 'x' or e.othercolumn3='y')
)
or (c.column1 is not null
and (d2.othercolumn2 = 'x' or d2.othercolumn3='y' or e2.othercolumn2 = 'x' or e2.othercolumn3='y')
)
您可以在sqlfiddle
上查看
您可以随时使用 exists
:
select a.*
from tablea a
where exists (select 1 from tableb b where a.column1 = b.column1 and b.column3 = 7) or
exists (select 1 from tablec c where a.column1 = c.column1 and c.column3 = 7);
当您使用 join
时,您 运行 有获得重复行的风险 -- 然后您可能会做额外的工作来删除重复项。 exists
.
都是不必要的
而且,为了提高性能,您需要在 tableb(column1, column3)
和 tablec(column1, column3)
上建立索引。
我看到了一些关于这个主题的问题,但坦白说我不太明白。
我想要什么:我有五个 table,我想 return 一个 select 与主要 table 与其他 4 个的所有交叉点。我我目前正在做 2 selects,然后是 UNION。它工作得很好,但我想我可以在单个 select.
中提高性能这是我的代码示例:
SELECT column1 FROM tableA A
INNER JOIN table B ON A.column1 = B.column1
LEFT JOIN table D ON A.column1 = D.column1
LEFT JOIN table E A.column1 = E.column1
WHERE B.column2 IS NOT NULL
AND B.column3 = '7'
AND ( (D.column2 = 'x' OR D.column3 = 'y') OR (E.column2 = 'x' OR E.column3 = 'y') )
UNION
SELECT column1 FROM tableA A
INNER JOIN table C ON A.column1 = C.column1
LEFT JOIN table D ON A.column1 = D.column1
LEFT JOIN table E A.column1 = E.column1
WHERE C.column2 IS NOT NULL
AND C.column3 = '7'
AND ( (D.otherColumn2= 'x' OR D.otherColumn3 = 'y') OR (E.otherColumn2 = 'x' OR E.otherColumn3 = 'y') )
关于 tables.
Table A 与所有其他 table 共享 column1
:
(int) column1
Tables B和C结构相同如下:
(int) column1 | (int) column2 | (varchar) column3
和tables D和E也有相同的结构:
(int) column1 | (varchar) otherColumn2 | (varchar) otherColumn3
正如我们所见,两个 select 几乎相同,除了 table B 和 C.
我在没有完整代码的情况下问了这个问题,@Kevin 解决了它。但是有了这些额外的信息,并尝试按照他的例子,我将代码更改为:
SELECT column1 FROM tableA A
LEFT JOIN table B ON (A.column1 = B.column1
AND C.column2 IS NOT NULL
AND C.column3 = '7')
LEFT JOIN table C ON (A.column1 = C.column1
AND C.column2 IS NOT NULL
AND C.column3 = '7')
LEFT JOIN table D ON A.column1 = D.column1
AND (D.otherColumn2 = 'x' OR D.otherColumn3 = 'y')
LEFT JOIN table E A.column1 = E.column1
AND (E.otherColumn2 = 'x' OR E.otherColumn3 = 'y')
WHERE
B.column1 is not null
or c.column1 is not null
or D.column1 is not null
or E.column1 is not null
但是我得到了很多额外的结果。我希望我在这里说清楚了,如果没有,请告诉我,我会更新这个问题。
这应该可以满足您的需求。不过,我不知道性能会好到什么地步。
SELECT A.column1 FROM tableA A
LEFT JOIN tableB B ON A.column1 = B.column1
AND B.column2 IS NOT NULL
AND B.column3 = '7'
LEFT JOIN tableD d ON b.column1 = D.column1
LEFT JOIN tableE e ON B.column1 = E.column1
LEFT JOIN tableC C ON A.column1 = C.column1
AND C.column2 IS NOT NULL
AND C.column3 = '7'
LEFT JOIN tableD d2 ON c.column1 = d2.column1
LEFT JOIN tableE e2 ON c.column1 = e2.column1
WHERE (B.column1 is not null
and (d.othercolumn2 = 'x' or d.othercolumn3='y' or e.othercolumn2 = 'x' or e.othercolumn3='y')
)
or (c.column1 is not null
and (d2.othercolumn2 = 'x' or d2.othercolumn3='y' or e2.othercolumn2 = 'x' or e2.othercolumn3='y')
)
您可以在sqlfiddle
上查看您可以随时使用 exists
:
select a.*
from tablea a
where exists (select 1 from tableb b where a.column1 = b.column1 and b.column3 = 7) or
exists (select 1 from tablec c where a.column1 = c.column1 and c.column3 = 7);
当您使用 join
时,您 运行 有获得重复行的风险 -- 然后您可能会做额外的工作来删除重复项。 exists
.
而且,为了提高性能,您需要在 tableb(column1, column3)
和 tablec(column1, column3)
上建立索引。