【问题标题】:How to Anti Join in MSSQL when the join depends on data from a 3rd table当连接依赖于第三个表中的数据时,如何在 MSSQL 中反连接
【发布时间】:2017-07-07 01:58:30
【问题描述】:

这是我的情况。

PayTable
+-------+------+--------------+
| Craft | Job  | sequence     |
+-------+------+--------------+
| 400   | 1    | 1            |
+-------+------+--------------+
| 401   | 2    | 2            |
+-------+------+--------------+
| 5501  | 2    | 3            |
+-------+------+--------------+

Jobs
+-------+------+------+
| Job | CraftTemplate |
+-------+------+------+
| 1   | 1             |
+-------+------+------+
| 2   | 1             |
+-------+------+------+


Pay Template
+-------+--+
| Template |
+-------+--+
| 1        |
+-------+--+

PayCraftTemplate
+-------+------+---------+
| PayTemplate    | Craft |
+-------+------+---------+
| 1              | 400   |
+-------+------+---------+
| 1              | 401   |
+-------+------+---------+

我需要做的是从 PayTable 中找到 PayCraftTemplate 中不存在该工艺的所有工艺。作为一种反连接模式,这似乎很简单,但我似乎无法让数据正确返回。

加入链接是:

PayTable INNER JOIN Jobs by Job -> Job
Jobs LEFT OUTER JOIN Pay Template by CraftTemplate -> Template
Pay Template LEFT OUTER JOIN by Template -> PayTemplate 

这是我目前的尝试:

select
    *
FROM
    PayTable
WHERE NOT EXISTS (
    SELECT 1
        FROM
    Jobs 
        LEFT OUTER JOIN PayTemplate
        ON PayTemplate.Template = Jobs.CraftTemplate
    LEFT OUTER JOIN PayCraftTemplate 
        ON PayCraftTemplate.Template = PayTemplate.Template
    WHERE 
        PayTable.Craft = PayCraftTemplate.Craft AND PayTable.Job = Jobs.Job
) AND PayTable.Job IS NOT NULL AND PayTable.Craft IS NOT NULL

这没有返回我期望的数据,我希望 PayTable 的第 3 行只返回而不是我得到第 1,2 行

【问题讨论】:

    标签: sql-server join anti-join


    【解决方案1】:

    我猜你移动了一些东西来发布问题并基本上解决了它。从上面的查询中,你只需要把PayCraftTemplate.Template改成PayCraftTemplate.PayTemplate

    起初我认为这是left joinwhere 无意间将其变成inner join 的问题,但在这种情况下,无论如何都需要inner join,所以这不是问题所在。

    select    *
    from  PayTable
    where not exists (
      select 1
      from Jobs 
        inner join PayTemplate
          on PayTemplate.Template = Jobs.CraftTemplate
          and Jobs.Job = PayTable.Job
        inner join PayCraftTemplate 
          on PayCraftTemplate.PayTemplate = PayTemplate.Template
         and PayCraftTemplate.Craft  = PayTable.Craft 
      )
      and PayTable.Job is not null
      and PayTable.Craft is not null
    

    结果:

    +-------+-----+----------+
    | Craft | Job | sequence |
    +-------+-----+----------+
    |  5501 |   2 |        3 |
    +-------+-----+----------+
    

    【讨论】:

    • 为什么在内部连接中链接 PayTable 而不是在内部子选择上执行 where 子句?
    • 这是我将 where 子句移动到连接时留下的,因为它是 left join。他们可以回到where 子句。我刚刚完成了我的答案的编辑,展示了您的答案如何在修正错字的情况下发挥作用。
    • @JeremyKeczan 是的!非常接近!
    猜你喜欢
    • 2012-02-06
    • 2023-01-29
    • 1970-01-01
    • 2021-11-11
    • 2019-08-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-20
    相关资源
    最近更新 更多