【问题标题】:SQL Query: Joining two tables where entity of the first table has no, or multiple entries in other tableSQL查询:连接两个表,其中第一个表的实体没有,或者另一个表中有多个条目
【发布时间】:2011-09-12 10:39:48
【问题描述】:

我必须数据库表,其中第一个表的实体在第二个表中可能有也可能没有关联条目:

Table 1          Table 2       
+-----+-----+    +-----+-------+-------+
| ID  | ... |    | ID  | T1_ID | NAME  |
+-----+-----+    +-----+-------+-------+
|  1  | ... |    |  1  |   1   |  p1   |
|  2  | ... |    |  2  |   1   |  p2   |
|  3  | ... |    |  3  |   2   |  p1   |
|  4  | ... |    +-----+-------+-------+
+-----+-----+

我需要运行以下查询:

  1. 使用 Table_2 的特定条目获取 Table_1 的所有实体 - 这很简单,一个简单的 Join 就可以了...

  2. 获取 Table_1 的所有实体,这些实体没有关联 Table_2 的特定条目 - 不是那么容易,但我也设法通过连接查询。

  3. 获取 Table_1 的所有实体,这些实体具有特定条目 (A) 并且没有关联的另一个特定条目 (B),即获取 Table_1 的所有实体,它们具有 Table_2 的实体 name=p1 和没有关联 name=p2 的 Table_2 实体。

是否可以在没有子查询的情况下在单个 sql 语句中完成 (3) 中的那种查询?

【问题讨论】:

  • 这不是一个“让别人为你做你的工作”的论坛。但是,如果您想这样做,您至少可以提供示例数据并采样所需的输出。
  • 嗯,最简单的情况下,我只想获取表1对应的ID。我上面的示例数据是不是不够?
  • @user655145,你能分享第2点的查询吗?

标签: mysql sql database join


【解决方案1】:

获取 Table_1 的所有实体,其中 有一个特定的条目 (A) 并且没有 有另一个特定条目 (B) 关联,即获取所有实体 具有 Table_2 实体的 Table_1 name=p1 并且没有实体 与 name=p2 关联的 Table_2。

我在理解您的标准时遇到了一些麻烦,但我认为这就是您想要的:

SELECT * 
FROM Table1 t1 
JOIN Table2 t2 ON t1.ID = t2.t1_id 
WHERE t2.name = 'p1' 
AND NOT EXISTS(SELECT 'x' FROM Table2 t2_2 WHERE t1.ID = t2_2.t1_id AND t2_2.name = 'p2')

这将为您提供 Table1 中的所有内容,这些记录在 Table2 中具有名称 = 'p1' 的匹配记录,并且在 Table2 中没有名称 = 'p2' 的匹配记录。这是你需要的吗?

再次编辑:

我想到了一种更聪明的方法,它涉及静态(非相关)子查询。该子查询只会执行一次,而不是对 Table1 中的每个父行执行一次。我没有通过查询分析器输入这段代码,但它应该比使用 EXISTS(...) 的查询快得多

SELECT * 
FROM Table1 t1 
JOIN Table2 t2 ON t1.ID = t2.t1_id 
WHERE t2.name = 'p1' 
AND t1.id NOT IN(SELECT t1_id FROM Table2 WHERE name = 'p2')

【讨论】:

  • 是的,这或多或少是我想要的,但是,我想知道如果没有子查询,这样的事情是否可能......抱歉不准确。
  • @donneo 我添加了第二个仅使用联接的查询。如果您的索引设置正确,它可能比使用子查询的版本更快,但如果没有测试数据就很难说。
  • @ean5533 是的,我来到了一个类似的“双重”加入自己,但我仍然没有用这种方法得到正确的结果...... :-(
  • @donneo 你说得对,我很抱歉,第二个查询不起作用。我已将其从我的答案中删除。你必须使用 NOT EXISTS 子查询来获得你想要的。
  • @donneo 这取决于服务器查询优化器的工作方式,但是所有主要的 DBMS 优化器都足够聪明,可以查看子查询并确定其结果永远不会改变。 “静态子查询”可能不是正确的术语,但这就是想法。如果您查看子查询,您会发现它没有引用主查询中的任何内容,因此无需多次执行它。大多数优化器足够聪明,可以注意到并执行一次,然后缓存结果。 Oracle、MySQL 和 MS SQL Server 肯定都这样做。
【解决方案2】:

您可以使用EXISTS 子查询(实际上与执行两个连接相同)。

SELECT * FROM Table_1 AS t1
WHERE EXISTS (SELECT * FROM Table_2 AS t2 WHERE t1.Id = t2.Id AND Name='p1')
AND NOT EXISTS (SELECT * FROM Table_2 AS t2 WHERE t1.Id = t2.Id AND Name='p2')

【讨论】:

    【解决方案3】:

    要获取 t2 匹配 t1.id 但不匹配其他字段的所有匹配项

    SELECT t1.id, t2.id FROM table2 t2
    INNER JOIN table1 t1 ON (t2.t1_id = t1.id AND not(t2.fieldx <=> t1.fieldx))
    

    请注意,这也将排除 fieldxnull 的行。
    如果您不希望将&lt;=&gt; 替换为=

    【讨论】:

      【解决方案4】:

      为了使解决方案的变化更加完整:

      SELECT t1.*
      FROM Table_1 t1
        INNER JOIN Table_2 it2 ON t1.ID = it2.T1_ID AND it2.NAME = 'p1'
        LEFT JOIN Table_2 lt2  ON t1.ID = lt2.T1_ID AND lt2.NAME = 'p2'
      WHERE lt2.ID IS NULL
      

      【讨论】:

        猜你喜欢
        • 2014-03-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-11-17
        • 1970-01-01
        • 2014-09-30
        相关资源
        最近更新 更多