【问题标题】:Joining a view using an ID from external joining使用来自外部加入的 ID 加入视图
【发布时间】:2016-02-18 09:25:25
【问题描述】:

我正在与SQL Server 合作,我在加入一些表格时遇到了困难。

这里是场景:

我有以下表格:

  • 系统
  • 区域
  • 转让

有关表格的更多信息:

  • 每个区域可以有多个系统,但一个系统只能在一个区域中。
  • 一个系统可以有多个传输,但一个传输元组只能与一个系统关联。

SystemArea 可以按照通常的方式加入,但是对于传输表,我想检索特定数据,然后加入SystemArea

这是我的查询

SELECT
    System.*,
    Transferring.SomeAttribute 
FROM
    System INNER JOIN
    Area ON Area.ID = System.AreaID INNER JOIN
    (
        SELECT TOP 1
            SomeAttribute,
            SystemID
        FROM
            Transfer
        WHERE
            Transfer.SystemID = {System ID ?}
        ORDER BY
            Transfer.Date DESC
    ) Transferring ON Transferring.SystemID = System.ID
WHERE
    Area.ID = @AreaID

上面的问题是我想在Transferring 视图中按SystemID 过滤并只返回TOP 1

如果我从view 中删除WHERE 子句并仅保留连接时的SystemID = System.ID 将返回错误数据,因为TOP 1 将首先发生,然后是SystemID = System.ID

另一方面,我想在一个 SELECT 语句中实现它,并且我不想使用两个不同的查询。

只是为了从上面的查询中弄清楚我想要什么:
我想获取一个区域中所有系统的信息,以及每个系统的SomeAttribute,但最近的Transfer 表将包含每个系统的多个传输。

【问题讨论】:

    标签: sql sql-server sql-server-2008 select join


    【解决方案1】:

    您可以使用row_number() 窗口函数查找每个系统的最新传输,然后过滤掉这些行:

    SELECT
        System.*,
        Transferring.SomeAttribute 
    FROM
        System 
    INNER JOIN
        Area ON Area.ID = System.AreaID
    INNER JOIN (
        SELECT 
            SomeAttribute,
            SystemID,
            ROW_NUMBER() OVER (PARTITION BY SystemID ORDER BY Date DESC) AS rn
        FROM
            Transfer
        ) Transferring ON Transferring.SystemID = System.ID AND rn = 1
    WHERE
        Area.ID = @AreaID
    

    【讨论】:

    • 谢谢。硬编码rn = 1的原因是什么?是一个例子吗?
    • 内部查询为每一行分配一个行号(名为rn),其中编号按日期的降序完成(参见内部order by 子句),每个不同的@987654327 @(参见partition by 子句)。由于您的要求是显示每个系统的最新传输的SomeAttribute,因此根据上述顺序,这将是第一个(rn=1)记录。
    • 这不会导致对 Transfer 进行表扫描,还是优化器会解决这个问题?在嵌套的 SELECT 中执行 WHERE 不是更好吗?即SELECT Transferring.* FROM ( SELECT System.*, SomeAttribute, ROW_NUMBER() OVER (PARTITION BY SystemID ORDER BY Date DESC) AS rn FROM System INNER JOIN Transfer ON Transfer.SystemID = System.ID WHERE System.AreaID = @AreaID ) Transferring WHERE Transferring.rn = 1
    • @strickt01 我希望优化器能够正确处理这样的连接,但我承认我还没有使用 MS-SQL 验证这一点。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-21
    • 1970-01-01
    • 2023-04-02
    • 2022-07-23
    • 2015-08-03
    • 1970-01-01
    相关资源
    最近更新 更多