SQL中的递归滞后列计算

Rob*_*ert 2 sql sql-server recursion

我正在尝试编写一个将计算的表数据插入另一个表的过程.

我遇到的问题是我需要每行的计算列受前一行计算列的结果的影响.我试图延迟计算本身,但这不起作用!

如:

(Max是我创建的函数,返回两个值中的最高值)

Id   Product      Model      Column1    Column2
1    A            1          5          =MAX(Column1*2, Lag(Column2))
2    A            2          2          =MAX(Column1*2, Lag(Column2))
3    B            1          3          =MAX(Column1*2, Lag(Column2))
Run Code Online (Sandbox Code Playgroud)

如果我在SQL中尝试以上内容:

SELECT
    Column1, 
    MyMAX(Column1,LAG(Column2, 1, 0) OVER (PARTITION BY Product ORDER BY Model ASC) As Column2 
FROM Source
Run Code Online (Sandbox Code Playgroud)

...它说column2未知.

如果我LAG进行Column2计算,我得到的输出:

Select Column1, MyMAX(Column1,LAG(Column1*2, 1, 0) OVER (PARTITION BY Product ORDER BY Model ASC) As Column2

Id   Column1    Column2
1    5          10
2    2          10
3    3          6
Run Code Online (Sandbox Code Playgroud)

第3排为什么6?因为3*2> 2*2.

我想要的输出:

Id   Column1    Column2
1    5          10
2    2          10
3    3          10
Run Code Online (Sandbox Code Playgroud)

第3排为什么10?因为之前的结果是10> 3*2

问题是我不能滞后Column2的结果 - 我只能滞后于其他列或计算它们!

是否有使用LAG实现此目的的技术,还是我必须使用递归CTE?我读到LAG接替CTE所以我认为它是可能的.如果没有,这个'CTE'会是什么样子?

编辑:或者 - 我还能做些什么来解决这个计算?

Stu*_*tLC 5

编辑

事后看来,这个问题是运行分区的最大值Column1 * 2.它可以简单地完成

SELECT Id, Column1, Model, Product,
       MAX(Column1 * 2) OVER (Partition BY Model, Product Order BY ID ASC) AS Column2
FROM Table1;
Run Code Online (Sandbox Code Playgroud)

小提琴

原始答案

这是一种使用递归CTE完成此操作的方法,通过连接递增行号来完全没有LAG.我没有假设你Id是连续的,因此增加了额外的ROW_NUMBER().您没有提到任何分区,因此没有应用相同的分区.查询只是从第一行开始,然后投影当前Column1 * 2或前一个中的较大者Column2

WITH IncrementingRowNums AS
(
    SELECT Id, Column1, Column1 * 2 AS Column2, 
           ROW_NUMBER() OVER (Order BY ID ASC) AS RowNum
    FROM Table1
),
lagged AS
(
    SELECT Id, Column1, Column2, RowNum
    FROM IncrementingRowNums
    WHERE RowNum = 1

    UNION ALL

    SELECT i.Id, i.Column1, 
        CASE WHEN (i.Column2 > l.Column2) 
            THEN i.Column2 
            ELSE l.Column2 
        END, 
        i.RowNum
    FROM IncrementingRowNums i
    INNER JOIN lagged l
    ON i.RowNum = l.RowNum + 1
)
SELECT Id, Column1, Column2
FROM lagged;
Run Code Online (Sandbox Code Playgroud)

SqlFiddle在这里

编辑,重新分区

分区大致相同,只需拖动Model + Product列,然后在行编号中进行分区(即每次产品或模型重置时从1开始),包括CTE JOIN条件下的这些以及最终订购.

WITH IncrementingRowNums AS
(
    SELECT Id, Column1, Column1 * 2 AS Column2, Model, Product,
           ROW_NUMBER() OVER (Partition BY Model, Product Order BY ID ASC) AS RowNum
    FROM Table1
),
lagged AS
(
    SELECT Id, Column1, Column2, Model, Product, RowNum
    FROM IncrementingRowNums
    WHERE RowNum = 1

    UNION ALL

    SELECT i.Id, i.Column1, 
        CASE WHEN (i.Column2 > l.Column2) 
            THEN i.Column2 
            ELSE l.Column2 
        END, 
        i.Model, i.Product,
        i.RowNum
    FROM IncrementingRowNums i
    INNER JOIN lagged l
    ON i.RowNum = l.RowNum + 1 
    AND i.Model = l.Model AND i.Product = l.Product
)
SELECT Id, Column1, Column2, Model, Product
FROM lagged
ORDER BY Model, Product, Id;
Run Code Online (Sandbox Code Playgroud)

更新小提琴