左连接在查询后返回更多和更少的行

Posted

技术标签:

【中文标题】左连接在查询后返回更多和更少的行【英文标题】:Left join returning both more and less rows after query 【发布时间】:2019-04-04 16:53:34 【问题描述】:

我是 SQL 新手,我想寻求帮助。我有 2 个要加入的表,我想生成与表 1 相同的行数。

这是表格:

表 1

+----------+------------+---------+-------+
| ENTRY_ID | ROUTE_NAME | STATION | BOUND |
+----------+------------+---------+-------+
|        1 |         1A |    ABCC |     1 |
|        2 |         2C |    CBDD |     1 |
|        3 |          5 |    AAAA |     2 |
|        4 |         1A |    EEEE |     1 |
|        5 |         2B |    ASFA |     2 |
|        6 |          5 |    DSAS |     1 |
|        7 |          3 |    QWEA |     2 |
|        8 |          4 |    ASDA |     1 |
+----------+------------+---------+-------+

表 2

+------------+-------+---------+---------------+
| ROUTE_NAME | BOUND | STATION | STOP_SEQUENCE |
+------------+-------+---------+---------------+
|         1A |     1 |     AAA |             1 |  
|         1A |     1 |     ABC |             2 |
|         1A |     1 |     CDA |             3 |
|         1A |     2 |     ABC |             1 |
|         1A |     2 |     ADC |             2 |
|         1A |     2 |     ACA |             3 |

重复其他路线

表格的简短说明: Table 1 包含某些中转行程,中转路线为ROUTE_NAME,出发站为STATION,中转方向为BOUND(仅1/2)。 Table 2包含一组公交路线数据,字段与表1类似,停靠顺序为STOP_SEQUENCE

我想做的是使用STATIONBOUNDROUTE_NAME在表1中调用表2中的STOP_SEQUENCE。我使用的代码是:

SELECT t1.ENTRY_ID, t1.ROUTE_NAME, t1.STATION, t1.BOUND, t2.STOP_SEQUENCE
FROM T1 
LEFT JOIN t2 ON 
(t1.STATION LIKE '*' & t2.STATION & '*') AND
(t1.BOUND = t2.BOUND) AND
(t1.ROUTE_NAME = t2.ROUTE_NAME);

LIKE 是必须的,因为两个表的 STATION 字符串之间存在一些不匹配,可以由函数处理。

第一个问题是,为什么 LEFT JOIN 不能返回 TABLE 1 中的所有行?我有一个类似的代码可以在其他类似的表中使用。对于不匹配的数据(使用 LIKE 语句),为该特定行返回 NULL。但是,在此查询中返回的行数较少。

第二个问题是,使用 LIKE 语句,我从表 1 中返回符合我的条件的表 2 中的一行或多行(这在我的代码中发生了 2+ 行具有相同 @ 987654334@ 已被退回)。如何保持返回行的最小值?即如果找到两个STOP_SEQUENCE,则返回较低的那个。

为此苦苦挣扎了很长时间,非常感谢您的帮助!

更新 我发现句子 t1.STATION LIKE '*' & t2.STATION & '*' 导致第一个问题中缺少行。我已将其替换为 = 并且所有行都再次出现。但是我仍然需要这个 LIKE 子句,我该怎么办?

【问题讨论】:

【参考方案1】:

为什么 LEFT JOIN 不返回表 1 中的所有行?

我只能怀疑这是您测试的问题,因为您问题中发布的 SQL 代码将返回列 t1.ENTRY_IDt1.ROUTE_NAMEt1.STATIONt1.BOUND 中所有记录的值表t1,以及表t2 中满足表t1每个 记录的连接条件的所有记录的t2.STOP_SEQUENCE 值。

请注意,如果有多个记录满足表 t1 中给定记录的连接条件,这将返回表 t2 中的多条记录。这就引出了你的下一个问题:

使用 LIKE 语句,我从表 1 中返回与我的条件匹配的表 2 中的一个或多个行(这在我的代码中发生,即返回了具有相同 ENTRY_ID 的 2+ 行)。如何保持返回行的最小值?即如果找到两个 STOP_SEQUENCE,则返回较低的那个。

您可以使用min 函数通过简单的聚合来实现这一点:

select
    t1.entry_id,
    t1.route_name,
    t1.station, 
    t1.bound,
    min(t2.stop_sequence) as stopseq
from
    t1 left join t2 on
    t1.station like '*' & t2.station & '*' and
    t1.bound = t2.route_bound and
    t1.route_name = t2.route_name
group by
    t1.entry_id,
    t1.route_name,
    t1.station, 
    t1.bound

这将返回由t1.entry_idt1.route_namet1.stationt1.bound 持有的每个值组合定义的组中字段t2.stop_sequence 持有的最小值。


另外,请注意,您问题中的示例表 t2 不包含您发布的代码引用的字段 route_bound

【讨论】:

您的代码非常适合我,谢谢!但是,根据这里的代码,我怎样才能包含不符合 t1.station 要求的条目,例如 '' & t2.station & '',并返回 0 作为 stop_seq?跨度> 您可以将t2.stop_sequence 更改为Nz(t2.stop_sequence, 0) 以返回0 的空值。 对不起我的错误,让我在这里描述一下情况。对于我的问题一,我得到了 100,000 行而不是 140,000 行。使用您的代码后,我得到 100,000 行,但其中一些行包含不符合 LIKE 要求的 NULL 值。使用 Nz() 更新后,NULL 值变为 0。在我看来,问题的核心在于问题 1,我还没有找到解决方案 而且,我已经通过从我的代码中删除 LIKE 语句进行了测试,并且所有 140,000 个条目都返回了。但是我认为 LIKE 语句没有问题。

以上是关于左连接在查询后返回更多和更少的行的主要内容,如果未能解决你的问题,请参考以下文章

使用左连接的查询返回的行数较少

左连接优于内连接?

Union all 似乎没有按预期工作。返回更少的行

MySQL连接5种方式

外连接查询

如何与第一个匹配行左连接并用空填充其余部分?