当左连接记录不存在时,左连接上的内连接不返回记录

时间:2013-05-11 21:52:40

标签: mysql zend-framework left-join inner-join

|----------------------------|
|  Tbl_1                     |
|--------------|-------------|
|  id          |  name_1     |
|--------------|-------------|
|  1           |  t_1_rec_1  |
|--------------|-------------|

|------------------------------------------------------------|
|  Tbl_2                                                     |
|-------|--------------|-----------|------------|------------|
|  id   |  name_2      | tbl_1_id  |  tbl_3_id  |  tbl_4_id  |
|-------|--------------|-----------|------------|------------|
|  1    | t_2_rec_1    | 1         | 1          |  2         |
|  2    | t_2_rec_2    | 1         | 2          |  1         |
|-------|--------------|-----------|------------|------------|

|------------------------|
|  Tbl_3                 |
|----------|-------------|
|  id      |  name_3     |
|----------|-------------|
|  1       |  t_3_rec_1  |
|  2       |  t_3_rec_2  |
|----------|-------------|

|----------------------|
|  Tbl_4               |
|--------|-------------|
|  id    |  name_4     |
|--------|-------------|
|  1     |  t_4_rec_1  |
|  2     |  t_4_rec_2  |
|--------|-------------|


|--------------------------------------------|
| Tbl_5                                      |
|------|------------|------------|-----------|
|  id  |  name_5    |  tbl_2_id  | tbl_6_id  |
|------|------------|------------|-----------|
|  1   | t_5_rec_1  |  1         | 1         |
|  2   | t_5_rec_2  |  1         | 2         |
|------|------------|------------|-----------|

|----------------------------------|
|  Tbl_6                           |
|-------|------------|
|  id   | name_6     |
|-------|------------|
|  1    | t_6_rec_1  |
|  2    | t_6_rec_2  |
|-------|------------|

我期待这些结果:

t1.name_1  t2.name_2  t3.name_3  t4.name_4  t5.name_5   t6.name_6

t_1_rec_1  t_2_rec_1  t_3_rec_1  t_4_rec_2  t_5_rec_1   t_6_rec_1
t_1_rec_1  t_2_rec_1  t_3_rec_1  t_4_rec_2  t_5_rec_2   t_6_rec_2
t_1_rec_1  t_2_rec_2  t_3_rec_2  t_4_rec_1

select t1.name_1, t2.name_2, t3.name_3, t4.name_4, t5.name_5, t6.name_6
from Tbl_1 as t1
left join Tbl_2 as t2 on t2.id = t1.id
inner join Tbl_3 as t3 on t2.tbl_3_id = t3.id
inner join Tbl_4 as t4 on t2.tbl_4_id = t4.id
left join Tbl_5 as t5 on t5.id = t2.id
inner join Tbl_6 as t6 on t2.tbl_6_id = t6.id

但这不起作用!!!!!第三行未返回。将最后一个内连接(Tbl_6)更改为左连接会产生第三行。

我理解Tbl_5和Tbl_6之间的内部连接将导致没有Tbl_5记录但是我希望Tbl_2和Tbl_5之间的左连接将导致Tbl_2并且其内部连接的Tbl_3和Tbl_4记录在那里并且因此Tbl_1离开加入Tbl_2,我会得到第三行。

我错过了什么? (我宁愿不必更改内连接,因为我不希望Tbl_5记录在后面没有Tbl_6条目)此外,此查询是从Zend Db类生成的,我需要能够将任何答案纳入其中,但我想如果有一个正常的查询,或者正如我所期望的那样,那么我将弄清楚如何让Zend生成它......

1 个答案:

答案 0 :(得分:0)

在SQL(和MySQL)中,inner joinleft outer joinright outer joincross join操作都具有相同的优先级。因此,a left join b inner join c(a left join b) inner join c。同样,算术表达式1 - 2 + 3(1 - 2) + 3而不是1 - (2 + 3)

考虑到这一点,让我们看一下你的from条款:

from Tbl_1 as t1
left join Tbl_2 as t2 on t2.id = t1.id
inner join Tbl_3 as t3 on t2.tbl_3_id = t3.id
inner join Tbl_4 as t4 on t2.tbl_4_id = t4.id
left join Tbl_5 as t5 on t5.id = t2.id
inner join Tbl_6 as t6 on t2.tbl_6_id = t6.id

第一个内部联接是t2.tbl_3_id = t3.id。如果t2.tbl_3_id表上的t1没有匹配,则列t2将为NULL。由于NULL值不匹配,因此效果是将第一个连接转换为内连接。

您可以使用以下语法解决此问题:

inner join Tbl_3 as t3 on t2.tbl_3_id = t3.id or t2.id is null

(NULL比较是t2.id而不是t2.tbl_3_id,以防id在有效匹配中id为NULL。)

您可以为后续连接继续此逻辑。

外连接和内连接的混合会自动将外连接转换为内连接。这取决于on子句中的条件。

就个人而言,我发现遵循连接的语义相当繁琐。我只使用内连接或只使用左外连接来编写几乎所有查询。也就是说,要么保留所有匹配的行,要么保留第一个表中的所有行。

如果我想混合连接类型,那么我有两个选择。第一种是使用子查询 - 在MySQL中,可能会导致性能问题。或者,我使用left outer join并在where子句中添加条件以实现我想要的逻辑。