Select 语句从关系较远的表中获取属性

问题描述 投票:0回答:2

我有一个库存表。我们称之为 INV。
我还有另一个对象的特定 ID。我们称之为 MyID。
我想要一个 select 语句,它可以从 INV 中获取几列,并从几步之外的表中获取一列:

有表 B,我们需要其中的所有“sID”值,其中“bID”= MyID 且 SomeOtherColumn = 1。

如果我们获取这些结果,然后查看另一个表 S,我们会发现每个 sID 与 INV 表中的一个 ID 完全一致。所以现在我们对每个 INV 行与一个 sID 都有一对一的关系。

然后我们有表 T。T 中的每一行都有一个 sID、一个 tID 和一个 Date。这 3 个值的每个组合都是唯一的。

我们还有一个名为 T_Lookup 的表。表T中的tID是与T_Lookup相关的外键。 T_Lookup 有一个名为“Type”的列,其中一个可能的值为“Approved”。

所以这就是我需要做的:我需要选择一些 INV 列和 表 T 中的最早日期,其中 tID 表示 T_Lookup 中的“已批准”类型,而 sID 是与相关 INV 行对应的类型 .

我希望这是有道理的。最终查询将类似于

SELECT Aa, Bb, Cc, Date
FROM INV
LEFT JOIN (
 --some convoluted thing that ultimately just needs Date plus an inventory ID for the join
) S
ON INV.ID = S.InventoryId

SQL 中事物的排序让我感到困难。概念化这一点要容易得多:“从 T 表中,对于 B 表中具有 SomeOtherColumn = 1 和 bID = MyID 的每个 sID,获取最早‘批准’T 的日期并将其附加到该sID对应的INV对象。”

注意事项:

  • 是的,每个 sID 将至少有一个“已批准”T。可能不止一个,但请记住,sID + tID + 日期的组合将是唯一的,这意味着只有一个“最早批准的 T”那个 sID。 [编辑添加:同一日期不可能有 2 个“已批准”T。]
  • 请记住,B 表中的 sID 具有 SomeOtherColumn = 1 且 bID = MyID 是我们在 sID 和 INV.ID 之间建立一对一关系的方式,因此,尽管这听起来多么令人费解,是的,总会有一旦我们让这个查询工作起来,每个 INV.ID 就只有一个日期。 (S表中每个INV.ID都有多个sID,这就是为什么我们必须先引用B表来过滤sID。)
sql sql-server
2个回答
1
投票

我并不是100%清楚你问的是什么,但在读了你的问题几次后,我会尝试一下。这是我对您可能正在寻找的东西的看法 -

    SELECT Aa, Bb, Cc, Date
FROM INV
LEFT JOIN (
 --select the first result with the correct WHERE clause and ensure that you're ordering the results by Date in desc order
    SELECT TOP 1 sID FROM [table].[B] 
    INNER JOIN [table].[T] ON T.sID = B.sID
    INNER JOIN [table].[T_Lookup] ON T_Lookup.tID = T.tID 
    WHERE   B.bID = INV.MyID 
        AND SomeOtherColumn = 1         
        AND T_Lookup.Type = 'Approved'
    ORDER BY T.Date DESC
) S
ON INV.ID = S.InventoryId

0
投票

您只需应用您的联接,就像您所说的那样。您可以通过交叉应用或使用 row_number 对结果进行排序来解决问题的“最早”部分,并为每个组取第一个(我认为在这种情况下,分组位于您感兴趣的 ID 上)。

注意:这些示例必然是“伪代码”而不是有效的解决方案,因为您的问题细节并不丰富。

带有 row_number 的示例(伪代码):

; with cte as (
select 
    inv.ID,
    t.[Date],
    row_number() over (
        partition by inv.ID
        order by t.[Date] desc) as SortOrder
from 
    dbo.INV inv
    inner join dbo.S s
    on s.sID = inv.ID
    inner join B b
    on b.sID = inv.ID
    and b.SomeOtherColumn = 1
    inner join dbo.T t
    on t.sID = inv.ID
    inner join dbo.T_Lookup tl
    on tl.tID = t.tID
    and tl.[Type] = 'Approved'
)
select * from cte where SortOrder = 1

交叉应用示例(伪代码):

select 
    inv.ID,
    t.[Date]
from 
    dbo.INV inv
    inner join dbo.S s
    on s.sID = inv.ID
    inner join B b
    on b.sID = inv.ID
    and b.SomeOtherColumn = 1
    inner join dbo.T t
    on t.sID = inv.ID
    cross apply (
        select top (1) tl.tID
        from dbo.T_Lookup tl
        where tl.tID = t.tID
        and tl.[Type] = 'Approved' 
        order by tl.[Date] desc
    ) ca
© www.soinside.com 2019 - 2024. All rights reserved.