左连接在查询后返回更多和更少的行
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
我想做的是使用STATION
、BOUND
和ROUTE_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_ID
、t1.ROUTE_NAME
、t1.STATION
和 t1.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_id
、t1.route_name
、t1.station
和t1.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 语句没有问题。以上是关于左连接在查询后返回更多和更少的行的主要内容,如果未能解决你的问题,请参考以下文章