【问题标题】:FULL JOIN on severals tables几个表上的 FULL JOIN
【发布时间】:2014-07-29 11:29:19
【问题描述】:

我有一个项目清单,按存款、库存、采购订单、销售订单、消费或生产预测等。我想为每个项目设置一个查询返回给我所有这些信息,存款由订金。显然,并不是说每个项目都有这个信息。

例如,考虑以下表格:

T1
|    REF |
|--------|
|      1 |

T2
|    REF |  DEPOT |
|--------|--------|
|      1 |      A |
|      1 |      B |

T3
|    REF |  DEPOT |
|--------|--------|
|      1 |      A |
|      1 |      C |

T4
|    REF |  DEPOT |
|--------|--------|
|      1 |      B |
|      1 |      C |
|      1 |      D |

如果我只取前三个表(刚开始),我还没有找到更好的方法:

SELECT T1.ref AS T1ref
  , T2.ref AS T2ref, T2.depot AS T2depot
  , T3.ref AS T3ref, T3.depot AS T3depot
FROM T1
  LEFT JOIN T2
    ON T2.ref = T1.ref
  FULL JOIN T3
    ON T3.ref = T1.ref
    AND T3.depot = T2.depot

输出:

|  T1REF |  T2REF | T2DEPOT |  T3REF | T3DEPOT |
|--------|--------|---------|--------|---------|
|      1 |      1 |       A |      1 |       A |
|      1 |      1 |       B | (null) |  (null) |
| (null) | (null) |  (null) |      1 |       C |

我想要什么:

|  T1REF |  T2REF | T2DEPOT |  T3REF | T3DEPOT |
|--------|--------|---------|--------|---------|
|      1 |      1 |       A |      1 |       A |
|      1 |      1 |       B | (null) |  (null) |
|      1 | (null) |  (null) |      1 |       C |

必须有一个干净的方法来做到这一点,但我没有找到任何东西。而且很难找到这方面的资料。

有人有提示吗?

sqlfiddle:http://sqlfiddle.com/#!3/19014/2

谢谢你, 大卫。

编辑:
T4:

|  T1REF |  T2REF | T2DEPOT |  T3REF | T3DEPOT |  T4REF | T4DEPOT |
|--------|--------|---------|--------|---------|--------|---------|
|      1 |      1 |       A |      1 |       A | (null) |  (null) |
|      1 |      1 |       B | (null) |  (null) |      1 |       B |
|      1 | (null) |  (null) |      1 |       C |      1 |       C |
|      1 | (null) |  (null) | (null) |  (null) |      1 |       D |

我应该用更好的名称来命名我的表:T1 = 物品,T2 = 库存,T3 = 购买,T4 = 销售。所以,T1 将始终拥有所有的 refs,以及我需要的许多其他信息。

【问题讨论】:

    标签: sql sql-server join outer-join


    【解决方案1】:

    您可以使用coalesce() 修复您的特定查询:

    SELECT coalesce(T1.ref, t2.ref, t3.ref) AS T1ref
    

    但是,我发现从我关心的列表和组合开始,而不是使用full outer join。在这种情况下,您似乎关心所有表格中的t1.refdepots。也许这更接近您真正想做的事情:

    SELECT t1ref.ref,
           T2.ref AS T2ref, T2.depot AS T2depot,
           T3.ref AS T3ref, T3.depot AS T3depot
    FROM (select ref from T1 union
          select ref from T2 union
          select ref from T3
         ) t1ref cross join
         (select depot from T2 union
          select depot from t3
         ) d LEFT JOIN T2
         ON T2.ref = T1ref.ref and
            t2.depot = d.depot LEFT JOIN
         T3
         ON T3.ref = T1ref.ref AND
            T3.depot = d.depot --OR T2.depot IS NULL)
    

    【讨论】:

    • 我应该用更好的名称来命名我的表:T1 = 物品,T2 = 库存,T3 = 购买,T4 = 销售。因此,T1 将始终拥有所有的裁判,以及我需要的许多其他信息。
    • @大卫。 . .好的。这不会影响第一个解决方案,它通过将第一个子查询替换为t1 来简化第二个解决方案。
    • 你说得对,有了正确的参考资料,我可以照顾我需要的其他信息。我在第一次阅读时误解了您的解决方案。谢谢。
    【解决方案2】:

    Gordon Linoff 所述的所有 4 个表和 Coalesce 的示例

    ;with[T1]([REF])as(
           select * from (values(1),(2))[A]([REF])
    ),
    [T2]([REF],[DEPOT])as(
           select*from(values
                 (1,'A'),
                 (1,'B'),
                 (1,'E')
           )[a]([REF],[DEPOT])
    ),
    [T3]([REF],[DEPOT])as(
           select*from(values
                 (1,'A'),
                 (1,'C')
           )[a]([REF],[DEPOT])
    ),
    [T4]([REF],[DEPOT])as(
           select*from(values
                 (1,'B'),
                 (1,'C'),
                 (1,'D'),
                 (1,'E')
           )[a]([REF],[DEPOT])
    )
    
    select
    *
    from [T1]
    outer apply (
          select
                T2.REF T2REF,
                T2.DEPOT T2DEPOT,
                T3.REF T3REF,
                T3.DEPOT T3DEPOT,
                T4.REF T4REF,
                T4.DEPOT T4DEPOT
          from T2
          full outer join T3 on
                T2.REF = T3.REF and
                T2.DEPOT = T3.DEPOT
          full outer join T4 on   
                COALESCE(T3.REF,T2.REF) = T4.REF and
                COALESCE(T3.DEPOT,T2.DEPOT) = T4.DEPOT
          where
            COALESCE(T2.REF,T3.REF,T4.REF) = T1.REF
    ) TR
    

    【讨论】:

      【解决方案3】:

      在你的帮助下,我发现如果我暂时忘记了物品信息(表T1),我几乎可以得到我想要的:

      SELECT *
      FROM T2
        FULL JOIN T3
          ON T3.ref = T2.ref
          AND T3.depot = T2.depot
        FULL JOIN T4
          ON (
            T4.ref = T2.ref
            AND T4.depot = T2.depot
          )
          OR (
            T4.ref = T3.ref
            AND T4.depot = T3.depot
          )
      

      它给出:

      |  T2REF | T2DEPOT |  T3REF | T3DEPOT |  T4REF | T4DEPOT |
      |--------|---------|--------|---------|--------|---------|
      |      1 |       A |      1 |       A | (null) |  (null) |
      |      1 |       B | (null) |  (null) |      1 |       B |
      | (null) |  (null) |      1 |       C |      1 |       C |
      | (null) |  (null) | (null) |  (null) |      1 |       D |
      

      然后我只需要获取 T1 信息:

      SELECT *
      FROM T2
        FULL JOIN T3
          ON T3.ref = T2.ref
          AND T3.depot = T2.depot
        FULL JOIN T4
          ON (
            T4.ref = T2.ref
            AND T4.depot = T2.depot
          )
          OR (
            T4.ref = T3.ref
            AND T4.depot = T3.depot
          )
        INNER/RIGHT JOIN T1
          ON T1.ref = COALESCE(T2.ref, T3.ref, T4.ref)
      

      获取:

      |  T2REF | T2DEPOT |  T3REF | T3DEPOT |  T4REF | T4DEPOT |  T1REF |
      |--------|---------|--------|---------|--------|---------|--------|
      |      1 |       A |      1 |       A | (null) |  (null) |      1 |
      |      1 |       B | (null) |  (null) |      1 |       B |      1 |
      | (null) |  (null) |      1 |       C |      1 |       C |      1 |
      | (null) |  (null) | (null) |  (null) |      1 |       D |      1 |
      

      为了好玩(以及更好地理解这个请求的目的),如果我将 T1 作为第一个表,我仍在尝试完成这项工作......

      (太糟糕了 sqlfiddle 似乎没有管理多个具有相同名称的字段...)

      【讨论】:

        猜你喜欢
        • 2013-04-16
        • 2019-05-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-06-02
        • 1970-01-01
        • 2017-10-20
        • 2021-10-24
        相关资源
        最近更新 更多