如何在 SQL AWS Athena 中使用动态偏移进行滞后?

问题描述 投票:0回答:1

我有一个表格,其中有一列数字,然后其他列包含其他数据。我创建了“floor10”列,其中这些数字的下限为 10 的倍数(例如 8 -> 0、17 -> 10 等)。我想做的是创建另一列,该列具有“floor10”的滞后并为每一行显示它。每个“floor10”的不同值没有固定的行数,因此我不确定如何在 AWS Athena 上的 SQL 中使用 LAG 来执行此操作。

例如,

数量 10楼 姓名
2 0 詹姆斯
23 20 詹姆斯
28 20 詹姆斯
16 10 詹姆斯
38 30 詹姆斯
8 0 约翰
54 50 约翰
56 50 约翰
28 20 约翰
22 20 约翰
25 20 约翰

我想要类似的东西,

数量 10楼 姓名 floor10_prev
2 0 詹姆斯
16 10 詹姆斯 0
23 20 詹姆斯 10
28 20 詹姆斯 10
38 30 詹姆斯 20
8 0 约翰
22 20 约翰 0
25 20 约翰 0
28 20 约翰 0
54 50 约翰 20
56 50 约翰 20

以下方法不起作用:

SELECT
Num,
floor10,
Name,
LAG(floor10) OVER (PARTITION BY Name, Num ORDER BY Name, Num) AS floor10_prev
FROM table

或者,我尝试使用不同的“floor10”和“Name”创建一个子查询,然后在加入主表之前对其使用滞后。虽然这得到了预期的结果,但这似乎效率不高,并且在更大的数据集上执行此操作需要很长时间才能完成。

sql amazon-athena presto
1个回答
0
投票

您可以创建一个 cte 来枚举每个名称 (Name_id) 的行并重复 10 层值,然后将其自连接到 Name_id - 1。

--    S a m p l e    D a t a :
Create Table tbl ( Num Int, floor10 Int, Name Varchar(32) );
Insert Into tbl
  VALUES  (  2,  0, 'James'  ), 
          ( 16, 10, 'James'  ),
          ( 23, 20, 'James'  ), 
          ( 28, 20, 'James'  ), 
          ( 38, 30, 'James'  ),
          ( 56, 50, 'John'   ), 
          (  8,  0, 'John'   ), 
          ( 22, 20, 'John'   ), 
          ( 25, 20, 'John'   ),
          ( 28, 20, 'John'   ),
          ( 54, 50, 'John'   ),
          ( 56, 50, 'John'   );
WITH
  grid AS
    ( Select   Name,
               Case When LAG(Coalesce(Name, 'XxX')) Over( Order By Name, Num ) = Name 
                    Then Sum(1) Over( Partition By Name 
                                       Order  By Name, Num
                                       Rows Between Unbounded Preceding And Current Row) 
               Else 1 
               End as Name_id,
               --
               Num, floor10,
               Row_Number() Over(Partition By Name, floor10 Order By Name, Num) as rn
      From     tbl
    )
--      M a i n    S Q L : 
Select     g1.Num, g1.floor10,  g1.Name, 
           Max( Case When g1.rn = 1 Then g2.floor10 End ) Over(Partition By g2.Name 
                                Order By g2.Name, g2.Num
                                Rows Between Unbounded Preceding And Current Row) as prev_floor10
From       grid g1
Left Join  grid g2 ON(g2.Name = g1.Name And g2.Name_id = g1.Name_id - 1)
Order By   g1.Name, g1.Name_id
/*    R e s u l t : 
Num  floor10  Name    prev_floor10
---  -------  ------  ------------
  2        0  James           null
 16       10  James              0
 23       20  James             10
 28       20  James             10
 38       30  James             20
  8        0  John            null
 22       20  John               0
 25       20  John               0
 28       20  John               0
 54       50  John              20
 56       50  John              20      */ 
© www.soinside.com 2019 - 2024. All rights reserved.