填补与具有填充数量限制的先前记录值的差距:无法使用分析

Fill in gap with prior record value having a populated quantity LIMIT: no analytics can be used

假设数据结构如下:Demo

WITH CAL AS(
SELECT 2022 YR, '01' PERIOD UNION ALL
SELECT 2022 YR, '02' PERIOD UNION ALL
SELECT 2022 YR, '03' PERIOD UNION ALL
SELECT 2022 YR, '04' PERIOD UNION ALL
SELECT 2022 YR, '05' PERIOD UNION ALL
SELECT 2022 YR, '06' PERIOD UNION ALL
SELECT 2022 YR, '07' PERIOD UNION ALL
SELECT 2022 YR, '08' PERIOD UNION ALL
SELECT 2022 YR, '09' PERIOD UNION ALL
SELECT 2022 YR, '10' PERIOD UNION ALL
SELECT 2022 YR, '11' PERIOD UNION ALL
SELECT 2022 YR, '12' PERIOD ),
Data AS (
SELECT 2022 YR, '01' PERIOD, 10 qty UNION ALL
SELECT 2022 YR, '02' PERIOD, 5 qty UNION ALL
SELECT 2022 YR, '04' PERIOD, 10 qty UNION ALL
SELECT 2022 YR, '05' PERIOD, 7 qty UNION ALL
SELECT 2022 YR, '09' PERIOD, 1 qty)

SELECT * 
FROM CAL A
LEFT JOIN data B
 on A.YR = B.YR
 and A.Period = B.Period
WHERE A.Period <10 and A.YR = 2022
ORDER by A.period

给我们:

+------+--------+------+--------+-----+
|  YR  | PERIOD |  YR  | PERIOD | qty |
+------+--------+------+--------+-----+
| 2022 |     01 | 2022 |     01 |  10 |
| 2022 |     02 | 2022 |     02 |   5 |
| 2022 |     03 |      |        |     |
| 2022 |     04 | 2022 |     04 |  10 |
| 2022 |     05 | 2022 |     05 |   7 |
| 2022 |     06 |      |        |     |
| 2022 |     07 |      |        |     |
| 2022 |     08 |      |        |     |
| 2022 |     09 | 2022 |     09 |   1 |
+------+--------+------+--------+-----+

预期结果为:

+------+--------+------+--------+-----+
|  YR  | PERIOD |  YR  | PERIOD | qty |
+------+--------+------+--------+-----+
| 2022 |     01 | 2022 |     01 |  10 |
| 2022 |     02 | 2022 |     02 |   5 |
| 2022 |     03 | 2022 |     03 |   5 | -- SQL derives
| 2022 |     04 | 2022 |     04 |  10 |
| 2022 |     05 | 2022 |     05 |   7 | 
| 2022 |     06 | 2022 |     06 |   7 | -- SQL derives
| 2022 |     07 | 2022 |     07 |   7 | -- SQL derives
| 2022 |     08 | 2022 |     08 |   7 | -- SQL derives
| 2022 |     09 | 2022 |     09 |   1 |
+------+--------+------+--------+-----+

问题: 如何用参考最近的较早 period/year 的创纪录数量来填补 03、06、07、08 期间的空白。注意示例仅限于一年,但差距可能在 2022 年第 01 期,我们需要 return 2021 年第 12 期数量(如果已填充)或继续返回直到找到数量,或者不存在此类记录。

限制:

为什么要限制?这必须在 HANA 图形计算视图中完成。这不支持这两个概念。我目前做的还不够,不知道如何进行相关子查询,不知道是否可行。

统计数据:

问题:

对于熟悉此问题的人,此问题源自 ECC 实现中的 MBEWH table

这可以通过 SAP HANA 中的图形计算视图来完成。

虽然它不是很漂亮而且可能不是很有效。 据称能够维护图形计算的人是否。 views but not SQL statement 就能成功维持这个很值得怀疑。

首先,SQL中的方法,使方法变得清晰:

create column table calendar
( yr integer
 , period nvarchar (2) 
 , primary key (yr, period))
 
 
 insert into calendar 
 ( select year (generated_period_start) as yr
        , ABAP_NUMC( month(generated_period_start), 2) as period 
   from series_generate_date ('INTERVAL 1 MONTH', '2022-01-01', '2023-01-01'));
 

create column table data
( yr integer
 , period nvarchar (2) 
 , qty integer
 , primary key (yr, period));
 
insert into data values (2022, '01', 10);
insert into data values (2022, '02', 5);
insert into data values (2022, '04', 10);
insert into data values (2022, '05', 7);
insert into data values (2022, '09', 1);
 
 
SELECT * 
FROM CALendar A
LEFT JOIN data B
 on A.YR = B.YR
 and A.Period = B.Period
 WHERE A.Period <'10' and A.YR =2022
ORDER BY  A.period;

/*
YR      PERIOD  YR      PERIOD  QTY
2,022   01      2,022   01      10 
2,022   02      2,022   02      5  
2,022   03      ?       ?       ?  
2,022   04      2,022   04      10 
2,022   05      2,022   05      7  
2,022   06      ?       ?       ?  
2,022   07      ?       ?       ?  
2,022   08      ?       ?       ?  
2,022   09      2,022   09      1  
*/

NUMC() 函数从整数创建 ABAP NUMC 字符串(带前导零)。除此之外,它几乎是来自 OP 的 tables。

一般的方法是使用 CALENDAR table 作为主要驱动 table 来确定 dates/periods 会有输出行。

这是与 DATA table 的外部连接,在相应的列中留下带有 NULL 的“缺失”行。

接下来,DATA table 再次加入,这次 YEAR||PERIOD 组合严格小于 CALENDAR YEAR||PERIOD table。这为我们提供了 allDATA.

中的先前记录

接下来,我们需要选择要查看的前几行。 这是通过 ROWNUM() 函数和对第一条记录的筛选器完成的。 由于图形计算视图不支持 ROWNUM() 这可以与 RANK() 交换 - 只要没有两个实际的 DATA 记录用于相同的 YEAR||PERIOD 组合,这就有效。

最后,在投影中,我们使用 COALESCEDATA 中可用的实际信息和 - 如果是 NULL - 上一周期信息之间切换。

/*
CAL_YR  CAL_PER COALESCE(DAT_YR,PREV_YR)    COALESCE(DAT_PER,PREV_PER)  COALESCE(DAT_QTY,PREV_QTY)
2,022   01      2,022                       01                          10                        
2,022   02      2,022                       02                          5                         
2,022   03      2,022                       02                          5                         
2,022   04      2,022                       04                          10                        
2,022   05      2,022                       05                          7                         
2,022   06      2,022                       05                          7                         
2,022   07      2,022                       05                          7                         
2,022   08      2,022                       05                          7                         
2,022   09      2,022                       09                          1                         
*/

到目前为止,还不错。

图形计算。视图看起来像这样:

由于对每个节点进行屏幕截图很麻烦,我将包括最重要的节点:

1. CAL_DAT_PREV

因为图形计算只支持等式连接。我们必须效仿“大于”连接的观点。为此,我创建了具有相同值的 calculated/constant 列 join_const(在本例中为整数 1)并加入了这些列。

2。 PREVS_ARE_OLDER

这是模拟“大于”联接的第二部分:此投影只是过滤掉 cal_yr_per 大于或等于 prev_yr_per 的记录。这里必须允许相等的值,因为我们不想丢失没有更小 YEAR||PERIOD 组合的记录。或者,可以将初始记录插入 DATA table,保证小于所有其他条目,例如YEAR= 0001PERIOD=00 或类似的东西。如果您熟悉 SAP 应用程序 table,那么您已经见过这种方法。

顺便说一下 - 为方便起见,我创建了计算列,将 YEARPERIOD 组合用于不同的 tables - cal_yr_perdat_yr_per, 和 prev_yr_per.

3。 RANK_1

此处为 PREV_YR_PR 创建排名,仅选择第一个,并为 cal_yr_per 的每个新值开始一个新组。 该值通过 Rank_Column.

返回

4. REDUCE_PREV

拼图的最后一块:在 Rank_Column = 1 上使用过滤器,我们确保每个“日历”行只得到一个“前一”行。

另外:通过 IF(ISNULL(...), ... , ...) 我们在三个计算列中模拟 COALESCE(...),恰当地命名为 FILL....

这就是该解决方案的具体细节。

“它在我的电脑上运行!” 可能是我能说的最好的了。

SELECT  "CAL_YR", "CAL_PERIOD"
      , "DAT_YR", "DAT_PER", "DAT_QTY"
      , "FILL_YR", "FILL_QTY", "FILL_PER" 
FROM "_SYS_BIC"."scratch/QTY_FILLUP"
ORDER BY "CAL_YR" asc, "CAL_PERIOD" asc;

/*
CAL_YR  CAL_PERIOD  DAT_YR  DAT_PER DAT_QTY FILL_YR FILL_QTY    FILL_PER
2,022   01          2,022   01      10      2,022   10          01      
2,022   02          2,022   02      5       2,022   5           02      
2,022   03          ?       ?       ?       2,022   5           02      
2,022   04          2,022   04      10      2,022   10          04      
2,022   05          2,022   05      7       2,022   7           05      
2,022   06          ?       ?       ?       2,022   7           05      
2,022   07          ?       ?       ?       2,022   7           05      
2,022   08          ?       ?       ?       2,022   7           05      
2,022   09          2,022   09      1       2,022   1           09      
2,022   10          ?       ?       ?       2,022   1           09      
2,022   11          ?       ?       ?       2,022   1           09      
2,022   12          ?       ?       ?       2,022   1           09      
*/