【问题标题】:Complex SQL Joins with Where Clauses使用 Where 子句的复杂 SQL 连接
【发布时间】:2020-11-16 20:33:17
【问题描述】:

对于 SQL 来说还是个新手,请耐心等待。我一直在努力想弄清楚如何通过加入 3 个表来创建这个 VIEW。我将使用模拟表等来保持这个非常简单。这样我就可以尝试理解答案 - 不只是复​​制和粘贴。

ICS_Supplies:

    Supplies_ ID      Item_Description
    -------------------------------------
     1            |     PaperClips
     2            |     Rubber Bands
     3            |     Stamps
     4            |     Staples

ICS_Orders:

    ID         SuppliesID            RequisitionNumber
    ----------------------------------------------------
    1    |      1             |        R1234a
    6    |      4             |        R1234a
    2    |      1             |        P2345b
    3    |      2             |        P3456c
    4    |      3             |        R4567d
    5    |      4             |        P5678e

ICS_Transactions:

    ID    RequsitionNumber      OrigDate      TransType    OpenClosed
    ------------------------------------------------------------------
    1    |  R1234a        |     06/12/20   |    Req      |    Open
    2    |  P2345b        |     07/09/20   |    PO       |    Open
    3    |  P3456c        |     07/14/20   |    PO       |    Closed
    4    |  R4567d        |     08/22/20   |    Req      |    Open
    5    |  P5678e        |     11/11/20   |    PO       |    Open

这就是我想在查看结果中看到的内容

    Supplies_ID    Item             RequsitionNumber  OriginalDate  TransType  OpenClosed
    ---------------------------------------------------------------------------------------
       1       |   Paper Clips   |   P2345b         |    07/09/20   |  PO     |  OPEN
       2       |   Rubber Bands  |   Null           |     Null      |  Null   |  Null
       3       |   Stamps        |   Null           |     Null      |  Null   |  Null
       4       |   Staples       |   P56783         |    11/11/20   |  PO     |  OPEN

我只是无法到达那里。我希望始终拥有与 ICS_Supplies 表中相同数量的记录。我需要加入 ICS_Orders 表才能获取申请编号,因为这是我需要加入 ICS_Transactions 表的内容。我不想在新添加的字段中看到数据,除非 ICS_Transactions.TransType = 'PO' AND ICS_Transactions.OpenClosed = 'OPEN',否则连接的字段应该被视为空,无论它们包含什么。如果可以吗?

我的研究表明这可能是一个 LEFT Join,这对我来说很新。我自己做了很多尝试,然后昨天发布了我的问题。但我一直在努力提出正确的问题,其他成员建议我再次发布问题。 .

如果需要,我可以分享我所做的事情,但我担心这会使事情变得过于混乱,因为我走错了方向。

我正在为需要一些背景信息的人添加原始问题的链接

Original Question

如果需要任何其他信息,请询问。如果我遗漏了任何需要的细节,我会提前道歉。

【问题讨论】:

  • 向我们展示您的 LEFT JOIN 尝试。
  • @jarlh - 我没有发布它,因为我分享了一个链接,其中包含我原来的问题、我原来的左连接和我之前所做的所有工作。我觉得在这里复制所有这些并不是一个好习惯。相反,我分享了一个链接——就像我的帖子说的那样。无论如何,现在已经回答了,但感谢您的帮助!

标签: sql subquery left-join inner-join


【解决方案1】:

这有点棘手,因为您想根据第三个表中是否存在匹配项来排除第二个表中的行 - 所以两个 left joins 不是您想要的。

我认为这实现了你想要的逻辑:

select s.supplies_id, s.item_description,
    t.requisition_number, t.original_date, t.trans_type, t.open_closed
from ics_supplies s
left join ics_transaction t
    on  t.transtype = 'PO' 
    and t.open_closed = 'Open'
    and exists (
        select 1 
        from ics_order o 
        where o.supplies_id = s.supplies_id and o.requisition_number = t.requisition_number
    )

另一种表达方式是在子查询中使用inner join,然后是left join

select s.supplies_id, s.item_description,
    t.requisition_number, t.original_date, t.trans_type, t.open_closed
from ics_supplies s
left join (
    select o.supplies_id, t.*
    from ics_order o
    inner join ics_transaction t 
        on t.requisition_number = o.requisition_number
    where t.transtype = 'PO' and t.open_closed = 'Open'
) t on t.supplies_id = s.supplies_id

【讨论】:

  • 感谢您发布此回复。第一个示例中的逻辑很容易理解(对于新手来说),它带来了我期望的结果。谢谢
【解决方案2】:

此查询应返回耗材数据。左连接将添加所有具有 supply_id 的订单(并为没有的订单返回 null)。

select
    s.supplies_id
    ,s.Item_Description as [Item]
    ,t.RequisitionNumber
    ,t.OrigDate as [OriginalDate]
    ,t.TransType
    ,t.OpenClosed
from ICS_Supplies s
    left join ICS_Orders o on o.supplies_id = s.supplies_id
    left join ICS_Transactions t on t.RequisitionNumber = o.RequisitionNumber
where t.TransType = 'PO'
    and t.OpenClosed = 'Open'

如果记录不存在,null 值将自动显示为 null。例如,您要加入 Transactions 表,如果该供应没有 transaction_id,那么它将返回“null”。

修改您的查询,运行它,然后如果可能的话,可能会使用真实示例更新您的问题。

【讨论】:

  • 您的 WHERE 子句在连接之后应用,此时 NULL 不符合条件,被排除,并将 OUTER 连接转换为 INNER 连接。
【解决方案3】:

在您写的原始问题中:

“我只需要 ICS_Transactions 表中的一条匹配记录。 理想情况下,我想要的是最新的 'ICS_Transactions.OriginalDate'。”

因此,目标是获取 TransType 为“PO”且 OpenClosed 为“Open”的最新事务。说明此代码中 CTE 'oa_cte' 的用途。然后在 SuppliesId 上左联接适当的事务。像这样的

with oa_cte(SuppliesId, RequsitionNumber, OriginalDate,
            TransType, OpenClosed, RowNum) as (
    select o.SuppliesId, o.RequsitionNumber, 
           t.OrigDate, t.TransType, t.OpenClosed, 
           row_number() over (partition by o.SuppliesId
                              order by t.OrigDate desc) 
    from ICS_Orders o
         join ICS_Transactions t on o.RequisitionNumber=t.RequisitionNumber
    where t.TransType='PO' 
          and t.OpenClosed='OPEN')
select s.*, oa.*
from ICS_Supplies s
     left join oa_cte oa on s.SuppliesId=oa.SuppliesId
                            and oa.RowNum=1;

【讨论】:

  • 是的,你是对的。在发布原始问题和现在之间,我了解到的一件事是,我了解到,对于同一个供应项目,永远不会有两个打开的采购订单,同时。所以。 . .我可能错误地使事情变得比需要的更复杂。我可能会在某些时候实现这一点,以保护视图的完整性。 . .随着应用程序随时间变化。这是一个 20 年前创建的旧应用程序,表格有拼写错误和不良做法。我需要花一些时间来清理和保护它
猜你喜欢
  • 1970-01-01
  • 2019-06-10
  • 2016-08-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多