复杂 SQL 与 Where 子句连接

Complex SQL Joins with Where Clauses

作为 SQL 的新手,请耐心等待。我一直在努力想弄清楚如何通过连接 3 个表来创建这个视图。我将使用模拟表等来保持这一点非常简单。这样我就可以尝试理解答案 - 不仅仅是复制和粘贴。

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 Table 中相同数量的记录。我需要加入 ICS_Orders Table 才能获取申请编号,因为那是我需要加入 ICS_Transactions Table。我不想在新添加的字段中看到数据,除非 ICS_Transactions.TransType = 'PO' AND ICS_Transactions.OpenClosed = 'OPEN',否则连接的字段应被视为空,无论它们包含什么。如果可以的话?

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

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

我正在为原始问题添加一个 link,以供那些需要一些背景信息的人使用

Original Question

如果需要任何其他信息,请询问。如果我遗漏了任何需要的细节,我深表歉意。

此查询应该return 用品的数据。左连接将添加所有具有 supply_id 的订单(对于没有的订单,return 为 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'

如果记录不存在,空值将自动显示为空。例如,您正在加入交易 table,如果该供应没有 transaction_id,那么它将 return 'null'.

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

这有点棘手,因为您想根据第三个 table 中是否存在匹配项来排除第二个 table 中的行 - 所以两个 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 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

你在原问题中写道:

"I only need ONE matching record from the ICS_Transactions Table. Ideally, the one that I want is the most current 'ICS_Transactions.OriginalDate'."

所以目标是获取TransType为'PO'且OpenClosed为'Open'的最新交易。即这段代码中 CTE 'oa_cte' 的目的。然后,适当的交易在 SuppliesId 上被 LEFT JOIN'ed。像这样

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;