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

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 语句没有问题。

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