【问题标题】:SQL Server: join on derived table that contains WITH clause?SQL Server:加入包含 WITH 子句的派生表?
【发布时间】:2011-02-10 16:53:06
【问题描述】:

我想加入一个包含 WITH 子句的子查询/派生表(WITH 子句是过滤ROW_NUMBER() = 1 所必需的)。在 Teradata 中类似的东西可以正常工作,但 Teradata 使用 QUALIFY ROW_NUMBER() = 1 而不是 WITH 子句。

这是我在此连接中的尝试:

-- want to join row with max StartDate on JobModelID
INNER JOIN (
    WITH AllRuns AS (
        SELECT *,
            ROW_NUMBER() OVER (PARTITION BY JobModelID ORDER BY StartDate DESC) AS RowNumber
        FROM Runs
    )
    SELECT * FROM AllRuns WHERE RowNumber = 1
) Runs
ON JobModels.JobModelID = Runs.JobModelID

我做错了什么?

【问题讨论】:

    标签: sql-server subquery row-number derived-table


    【解决方案1】:

    您可以使用多个 WITH 子句。类似的东西

    ;WITH AllRuns AS ( 
            SELECT  *, 
                    ROW_NUMBER() OVER (PARTITION BY JobModelID ORDER BY StartDate DESC) AS RowNumber 
            FROM    Runs 
    ),
    Runs AS(
            SELECT  * 
            FROM    AllRuns 
            WHERE   RowNumber = 1
    )
    
    SELECT  *
    FROM    ... INNER JOIN ( 
            Runs ON JobModels.JobModelID = Runs.JobModelID 
    

    有关用法/结构/规则的更多详细信息,请参阅WITH common_table_expression (Transact-SQL)

    【讨论】:

    • 丑陋,但它似乎工作。这里的根本问题是什么——派生表中缺乏对 WITH 子句的支持?此外,我可以通过加入 (SELECT * FROM AllRuns WHERE RowNumber = 1) 来消除第二个 WITH 子句。
    • 我不同意 with 子句中的多个 sattments 是丑陋的事实。 sintac 与多层子选择略有不同,这在大多数情况下使其极难阅读。
    • 我的意思是丑陋的意思是,用于执行子查询任务的 SQL(过滤 Runs 表以获得每个 JobModelID 的一行)现在在查询的开头和子查询之间拆分.
    【解决方案2】:

    添加连接条件可能效率较低,但通常对我来说效果很好。

    INNER JOIN (
        SELECT *,
               ROW_NUMBER() OVER 
               (PARTITION BY JobModelID 
               ORDER BY StartDate DESC) AS RowNumber
          FROM Runs
        ) Runs
    ON JobModels.JobModelID = Runs.JobModelID 
    AND Runs.RowNumber = 1
    

    【讨论】:

    • 知道这会降低多少效率吗?
    • @jnylen,您是否尝试过分析此查询?执行计划、分析器、客户统计?
    • @jnylen:我同意旁观者的观点。我的经验法则:如果查询在合理的时间内返回,就可以了。如果没有,我开始寻找热点并尝试重构。我从来不需要像上面展示的那样重构代码。
    • 我还没有足够的数据来解决问题(仍处于开发阶段)。无论如何,数据量可能会保持很小,所以我只是在寻找一些主观的东西。
    猜你喜欢
    • 1970-01-01
    • 2016-01-09
    • 2011-08-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多