【问题标题】:SQL How to Join 2 tables so that only matching records from Table 2 are shownSQL 如何连接 2 个表,以便只显示表 2 中的匹配记录
【发布时间】:2018-02-25 20:21:01
【问题描述】:

在 MS Access 中,我正在尝试搜索匹配的记录,以便只看到表 1 中与表 2 匹配的记录。无论我尝试什么,我最终都会在结果中获得更多记录设置比表 1 必须开始。我试过内连接,左连接......我不知道我做错了什么。

我只想要表 1 中与表 2 匹配的记录。

表 1 有 294,037 条记录

当我跑步时:

Select Table1.Key
From Table1
Inner Join Table2
On Table1.Key = Table.Key;

我的结果集有 4,428,853 条记录。

【问题讨论】:

  • 内连接应该是正确的连接类型。我唯一能想到的是,table1 和 table2 之间存在一对多的关系。例如,对于 table1 中的给定键,可能有不止一行与表 2 中的匹配。由于您的输出只是 table1.key 列,您可以尝试在查询中添加 distinct。
  • 应该Table.KeyTable2.Key
  • 为表 1 中的特定记录添加 where 子句。现在您知道该键使用它从表 2 中选择记录。请注意,对于该外键,您可能有许多记录。那么当发生这种情况时,您希望从表 2 中获得哪条记录?你现在得到的是一对多关系中的正常行为

标签: sql ms-access join


【解决方案1】:

除非您想要右侧有一行但左侧没有匹配行的行的 NULL 值(即RIGHT JOIN),否则听起来您想要一个“INNER JOIN”。但是,如果JOIN 条件匹配多行,您将在结果中获得多行。以下是它的工作原理:

  1. 找到左边的东西(查询中INNER JOIN之前指定的表),
  2. 找到右边的东西(查询中INNER JOIN后面指定的表),
  3. 接下来,根据指定条件(在ON 之后指定)从每一侧匹配行,
  4. 如果对于左侧的一个匹配行,右侧有一个匹配的行,则将左侧行的列值与列值放在一起从右表到结果中的一行
  5. 如果任一侧有多个匹配行,则从每一侧复制每一行,以便结果具有所有可能的匹配组合,并将它们放入结果中。李>

如果来自任一侧的单行数据多次显示在结果中,那只能是因为用于JOIN 的条件(ON 子句之后的条件)导致多行一侧匹配另一侧的一行或多行。

例如,如果我有以下两个表:

Table1 | Key | Value 
------ | --- | -----
       |  1  |    A1
       |  1  |    A2
       |  2  |    B
       |  3  |    C
       |  5  |    E


Table2 | Key | Value 
------ | --- | -----
       |  1  |    Z
       |  2  |    Y
       |  3  |    X1
       |  3  |    X2
       |  4  |    W

以下查询:

SELECT * FROM Table1 first 
RIGHT JOIN Table2 second ON first.Key=second.Key

将返回以下结果:

Table2 | Key | Value | Key | Value 
------ | --- | ----- | --- | -----
       |  1  |    A1 |  1  |    Z
       |  1  |    A2 |  1  |    Z
       |  2  |    B  |  2  |    Y
       |  3  |    C  |  3  |    X1
       |  3  |    C  |  3  |    X2
       |NULL |  NULL |  4  |    W

请注意,Table2 中的 1,Z 行在结果中出现了两次,而 A 中的 3,C 行也出现了两次。 4,W 出现是因为它是RIGHT JOINLEFT JOIN 会将 5,E 放入结果中,而 INNER JOIN(或只是简单的 JOIN)将没有这些行。 OUTER JOIN 将包含这两行。

如果 Table2 有两个键为 1 的条目(例如 Z1 和 Z2),则键为 1 的结果将有四个(一个为 A1、Z1,一个为 A2、Z1,一个为 A1、Z2,以及一个与 A2,Z2)。这是事情真正膨胀的地方,从你的数字来看,你可能有几个关键值就是这种情况。

如果 Table1 和 Table2 中的值都有相同的键值,则结果集将包含所有可能的值组合,因此结果集中的行数将是 Table1 中的行数 次 Table2 的行数。

WHERE 子句中的限制也可能会修剪与此处指定的所有条件不匹配的结果行​​。

对于INNER JOIN,除非在上面的步骤 4 中有多个匹配项,否则结果集中的行数不会超过源表中较小的一个。如果要确保只有一个匹配项,则两个表都必须具有唯一键(任何给定键只能有一行的键),您必须更改 ON 条件以将匹配限制为一行,或者您必须过滤 JOIN 的一侧,使其仅包含您要加入的行。

【讨论】:

    【解决方案2】:

    如果您只想要 Table1 中与 table2 匹配的记录,则使用 existsin 子句获得所需的输出。下面是相同的得到你的输出

    Select T1.Key From Table1 T1 where 
    exists (select 1 from Table2 T2 where T1.Key = T2.Key);
    

    【讨论】:

    • 这可行,但效率相当低。 DISTINCT 或 GROUP BY 查询可能会更好,这样访问就不需要为 Table1 中的每条记录执行子查询。但即使在考虑此解决方案之前,提问者也需要了解表和数据......例如,关系应该是一对多还是 Table2 中是否存在意外的重复条目。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-09
    • 1970-01-01
    • 1970-01-01
    • 2021-09-04
    • 1970-01-01
    • 2023-03-03
    相关资源
    最近更新 更多