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'会是什么样子?
编辑:或者 - 我还能做些什么来解决这个计算?
编辑
事后看来,这个问题是运行分区的最大值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)
编辑,重新分区
分区大致相同,只需拖动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)