复杂 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;
作为 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;