红移SQL:添加并重置考虑了日期和组的计数器

红移SQL:添加并重置考虑了日期和组的计数器,sql,amazon-redshift,counter,window-functions,lag,Sql,Amazon Redshift,Counter,Window Functions,Lag,假设我在下面有一张桌子。我想用一个计数器来计算a段中有多个客户的次数。如果客户在两个季度之间跳到不同的段,当客户跳回到a段时,计数器将重置。我确信有很多方法可以做到这一点,但我就是想不出这一点。请帮助。谢谢大家! Quarter Segment Customer *Counter* Q1 2018 A A1 1 Q2 2018 A A1 2 Q3 2018 A A1

假设我在下面有一张桌子。我想用一个计数器来计算a段中有多个客户的次数。如果客户在两个季度之间跳到不同的段,当客户跳回到a段时,计数器将重置。我确信有很多方法可以做到这一点,但我就是想不出这一点。请帮助。谢谢大家!

Quarter    Segment    Customer    *Counter*
Q1 2018    A          A1          1
Q2 2018    A          A1          2
Q3 2018    A          A1          3
Q4 2018    B          A1          1
Q1 2019    B          A1          2
Q2 2019    A          A1          1
Q1 2020    A          A1          *1* I want 1 not 2 here because it's not consecutive

这是一种缺口和孤岛问题。您可以通过行号的不同来解决这个问题。真正的问题是如何处理宿舍。但是字符串函数可以处理这个问题

select quarter, customer, segment,
       row_number() over (partition by customer, segment, seqnum - seqnum_cs order by right(quarter, 4), left(quarter, 2)) as counter
from (select t.*,
             row_number() over (partition by customer order by right(quarter, 4), left(quarter, 2)) as seqnum,
             row_number() over (partition by customer, segment order by right(quarter, 4), left(quarter, 2)) as seqnum_cs
      from t
     ) t
order by customer, seqnum;

这里的关键思想是,行号的差异定义了具有相同状态的客户的相邻行。很难理解为什么会出现这种情况。但是,如果您查看子查询的结果,您将毫无疑问地看到并理解这是如何工作的。

这是一种间隙和孤岛问题。您可以通过行号的不同来解决这个问题。真正的问题是如何处理宿舍。但是字符串函数可以处理这个问题

select quarter, customer, segment,
       row_number() over (partition by customer, segment, seqnum - seqnum_cs order by right(quarter, 4), left(quarter, 2)) as counter
from (select t.*,
             row_number() over (partition by customer order by right(quarter, 4), left(quarter, 2)) as seqnum,
             row_number() over (partition by customer, segment order by right(quarter, 4), left(quarter, 2)) as seqnum_cs
      from t
     ) t
order by customer, seqnum;

这里的关键思想是,行号的差异定义了具有相同状态的客户的相邻行。很难理解为什么会出现这种情况。但是,如果您查看子查询的结果,您无疑会看到并理解其工作原理。

您可以通过对季度、细分市场和客户列进行分区并分配排名来使用排名窗口功能。请阅读->示例->为什么B的计数器是1,2,它不应该是1,1,因为年份不同!但问题是,如果我按这3列进行分区,所有行中都会得到1,对吗?如果我只按段划分,按季度排序,我会得到A段1-5,B段1-2。我如何才能考虑到2018年第四季度和2019年第一季度的中断,并在2019年第二季度重新启动计数器?@事实上,这一年在这里并不重要,只要上一季度细分市场中的值在该行中与当前季度中的值相同,您就可以通过在季度、细分市场和客户列上划分并分配排名来使用排名窗口功能。请阅读->示例->为什么B的计数器是1,2,它不应该是1,1,因为年份不同!但问题是,如果我按这3列进行分区,所有行中都会得到1,对吗?如果我只按段划分,按季度排序,我会得到A段1-5,B段1-2。我如何才能考虑到2018年第四季度和2019年第一季度的中断,并在2019年第二季度重新启动计数器?@事实上,这一年在这里并不重要,只要上一季度该细分市场的价值与该rowNice当前季度的价值相同,我就过度简化了我的答案,然后意识到需要将季度和年份虚拟化为标记,这样才能起作用。@gordon linoff谢谢gordon linoff!这正是我要找的!还学习了“间隙和孤岛”一词@戈登·林诺夫你好,戈登,我有一个跟进-如果我们在这个季度有一些休息怎么办?我修改了问题中的表格:客户A1在2019年第3季度和第4季度不在任何细分市场,然后在2020年第1季度回到细分市场A。使用这里的方法,计数器将是2,但实际上它应该是1,因为它不是连续的。你知道怎么处理吗?谢谢@gordon linoff oh看起来我可以使用case语句添加一个新列来比较当前季度是否比上一季度晚一个季度,如果不是true,则强制它为1,否则使用计数器。然后我使用这个新的列进行排名,检查它是否是连续的。另外,如果前一个季度是空的,因为它是第一次出现,那么也只使用旧的计数器值。看起来像是working@user12562215 . . . 最好问一个新问题。你原来的问题已经得到了回答。很好,我把答案简化了,然后意识到需要将季度和年份虚拟化为标记,这样才能起作用。@gordon linoff谢谢你gordon linoff!这正是我要找的!还学习了“间隙和孤岛”一词@戈登·林诺夫你好,戈登,我有一个跟进-如果我们在这个季度有一些休息怎么办?我修改了问题中的表格:客户A1在2019年第3季度和第4季度不在任何细分市场,然后在2020年第1季度回到细分市场A。使用这里的方法,计数器将是2,但实际上它应该是1,因为它不是连续的。你知道怎么处理吗?谢谢@gordon linoff oh看起来我可以使用case语句添加一个新列来比较当前季度是否比上一季度晚一个季度,如果不是true,则强制它为1,否则使用计数器。然后我使用这个新的列进行排名,检查它是否是连续的。另外,如果前一个季度是空的,因为它是第一次出现,那么也只使用旧的计数器值。看起来像是working@user12562215 . . . 最好问一个新问题。哟 你原来的问题已经回答了。