我正在尝试编写一个将计算的表数据插入另一个表的过程。
我遇到的问题是我需要每行的计算列受上一行计算列结果的影响。我试图延迟计算本身,但这不起作用!
如:
(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))
如果我在SQL中尝试以上操作:
SELECT
Column1,
MyMAX(Column1,LAG(Column2, 1, 0) OVER (PARTITION BY Product ORDER BY Model ASC) As Column2
FROM Source
......它说第2列未知。
如果我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
第3行为什么6?因为3 * 2> 2 * 2。
我想要的输出:
Id Column1 Column2
1 5 10
2 2 10
3 3 10
第3行为什么10?因为先前的结果10> 3 * 2
问题是我不能滞后Column2的结果 - 我只能滞后于其他列或计算它们!
是否有使用LAG实现此目的的技术,还是我必须使用递归CTE?我读到LAG接替CTE所以我认为它是可能的。如果没有,这个'CTE'会是什么样的?
编辑:或者 - 我还能做些什么来解决这个问题?
答案 0 :(得分:5)
修改强>
事后看来,这个问题是在Column1 * 2
之上运行的分区最大值。它可以像
SELECT Id, Column1, Model, Product,
MAX(Column1 * 2) OVER (Partition BY Model, Product Order BY ID ASC) AS Column2
FROM Table1;
原始答案
通过加入递增的行号,这里有一种方法可以通过递归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;
修改,重新分区
分区大致相同,只需拖动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;