我有一张看起来像这样的表格:
Account Value Last_Day_in_Month
ABC 7 2018-06-30
ABC 12 2018-06-30
ABC 3 2018-08-31
FGH 57 2019-01-31
FGH 13 2019-03-31
FGH 127 2019-03-31
对于每个帐户,我需要填写对应于每个月最后一天的缺失日期,以便结果表只填写上个月的值(您会注意到额外的两行)
Account Value Last_Day_in_Month
ABC 7 2018-06-30
ABC 12 2018-06-30
ABC 12 2018-07-31
ABC 3 2018-08-31
FGH 57 2019-01-31
FGH 57 2019-02-28
FGH 13 2019-03-31
FGH 127 2019-03-31
我有很多帐户,每个帐户都有不同的开始和停止时间 (Last_Day_in_Month),所以我只需要填写每个帐户的最小和最大月份之间缺少的月份。因为我可能有多个值对应于每个帐户的一个单月结束日期,我当前的解决方案是使用带有 case 语句的线索,该语句添加一天和一个仅包含每个月最后一天的日期表并执行交叉加入。但是,我认为它很混乱,而且我确信有一种我不知道的更好的方法。这是我目前的解决方案...
select
*,
lead(Last_Day_in_Month,1)over (
partition by Account
order by Last_Day_in_Month
) as intermed2,
case
when intermed2 = Last_Day_in_Month
then dateadd('day',1, intermed2)
else intermed2
end as next_last_day
from table
cross join dates
where dates.date_actual >= table.Last_Day_in_Month
and dates.date_actual < table.next_last_day
感谢任何建议。
答案 0 :(得分:0)
对于合理的行数,您所做的一切都很好。为了清楚起见,我建议的一件事是从交叉联接更改为带有 ON 子句的右联接。查询计划员应该看透您拥有的内容并计划一个有效的查询,所以只需一点点。
还有许多其他方法可以做到这一点,您可以通过在堆栈溢出中搜索“间隙和孤岛”来找到示例。我得到的最大反馈是关于创建额外的行。您正在做的是为缺失的月份创建新行,这对于相当小的表来说很好,因为当您添加行时它们不会变得非常大。例如,如果您有一个包含 1000 亿行的表,并且平均间隙大小为 2,那么您将创建一个包含 3000 亿行的结果。制作这么多数据永远不会快速或高效。所以你说你有“很多账户”,多少就是多少?
如果数据量可以容纳在内存中,或者您只是偶尔执行一次此操作,那么创建行就可以了。如果这是作为正在进行的查询的一部分完成的,并且创建的数据会很大,那么我会重新考虑为什么您需要创建数据来执行查询。通常,Redshift 存储非常大的数据集,并且将这些行乘以其他因素(日期)(交叉连接)会导致查询速度非常慢。如果目的是将此数据缩减为某个较小的结果,您将需要找到一种方法来创建此结果,而无需制作如此大的中间数据集。