具有动态偏移量的 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

我知道您可以使用CTEJOIN 复制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 中,LAGalways 支持将列作为 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

具有限制和偏移量的 CodeIgniter sql 查询未显示结果

ORACLE 偏移分析函数 lag()与lead() 用法

ORACLE 偏移分析函数 lag()与lead() 用法

oracle lag与lead分析函数简介

在javascript中对具有偏移量的对象数组进行排序