具有动态偏移量的 TSQL 复制 LAG() 函数
Posted
技术标签:
【中文标题】具有动态偏移量的 TSQL 复制 LAG() 函数【英文标题】:TSQL Replicating LAG() function with dynamic offset 【发布时间】:2021-04-20 08:01:17 【问题描述】:我正在尝试在不使用 LAG()
的情况下重新创建 LAG()
函数,但有一个依赖于列的动态 Offset
。我要把这段代码复制到SparkSQL
。
这是我的示例数据:
if object_id('tempdb.dbo.#myTable') is not null drop table #myTable
create table #myTable (id int,dates int, flag char, FromToFlagType varchar(2),FromToCounter INT)
insert into #myTable values(1, '20181031','V','VV',1)
insert into #myTable values(2, '20181130','V','VV',2)
insert into #myTable values(3, '20181231','V','VV',3)
insert into #myTable values(4, '20190131','F','VF',1)
insert into #myTable values(5, '20190228','F','FF',2)
insert into #myTable values(6, '20190331','F','FF',3)
insert into #myTable values(7, '20190430','F','FF',4)
insert into #myTable values(8, '20190531','V','FV',1)
insert into #myTable values(9, '20190630','V','VV',2)
insert into #myTable values(10, '20190731','V','VV',3)
id dates flag FromToFlagType FromToCounter
1 20181031 V VV 1
2 20181130 V VV 2
3 20181231 V VV 3
4 20190131 F VF 1
5 20190228 F FF 2
6 20190331 F FF 3
7 20190430 F FF 4
8 20190531 V VF 1
9 20190630 V VV 2
10 20190731 V VV 3
所以我想做的是复制以下结果,但不使用动态Offset
:
select
*
,LAG(FromToFlagType,FromToCounter-1) OVER ( ORDER BY dates) AS FromToStage
from
#mytable
id dates flag FromToFlagType FromToCounter FromToStage
1 20181031 V VV 1 VV
2 20181130 V VV 2 VV
3 20181231 V VV 3 VV
4 20190131 F VF 1 VF
5 20190228 F FF 2 VF
6 20190331 F FF 3 VF
7 20190430 F FF 4 VF
8 20190531 V FV 1 FV
9 20190630 V VV 2 FV
10 20190731 V VV 3 FV
我知道您可以使用CTE
和JOIN
复制LAG()
,但它似乎只有在您提前知道偏移量的情况下才有效。我在这里尝试过类似的方法,但我无法获得相同的结果。
我发现了类似的here,但我是 Spark 的新手,我需要一个使用 SparkSQL
的解决方案。我想如果我可以复制这个功能,我可以将它复制到“Spark”。
WITH FromToStage AS(
select
*
,id-(FromToCounter-1) AS id_2
from #mytable
--order by dates
)
SELECT
a.*
,b.FromToFlagType as FromToStage
FROM
FromToStage a
JOIN
FromToStage b
ON
a.id = b.id_2
order by dates
【问题讨论】:
为什么要重新发明***?LAG
允许 offset 在其表达式中包含列。 db<>fiddle.
如果您必须重新发明***,请在 CTE 和自联接中使用 ROW_NUMBER
;但它的性能会差很多。
SparkSQL 不允许动态偏移,它需要是文字。 spark.apache.org/docs/2.3.1/api/sql/index.html我尝试了自我加入,只要我提前知道我的偏移量,它似乎就可以工作。
那么,如果您的目标 DBMS 是 SQL Server 实例,为什么不使用存储过程呢?在 T-SQL 中,LAG
always 支持将列作为 offset 定义的一部分。
我很困惑...你是想在 Spark 或 SQL Server 中做吗?
【参考方案1】:
根据你的逻辑,你想要first_value()
select t.*,
first_value(FromToFlagType) over (partition by seqnum - seqnum_2 order by date)_ as first_FromToFlagType
from (select t.*,
row_number() over order by date) as seqnum,
row_number() over (partition by flag order by date) as seqnum_2
from #mytable t
) t;
【讨论】:
谢谢!我意识到我在输入和输出示例中犯了一个小错误,但解决方案有效。以上是关于具有动态偏移量的 TSQL 复制 LAG() 函数的主要内容,如果未能解决你的问题,请参考以下文章
sql SQL Server 2012 TSQL新函数LAG,LEAD,FIRST_VALUE和LAST_VALUE