当前位置: 首页 > 面试题库 >

使用日期维度的每月快照

燕照
2023-03-14
问题内容

我有一些需要带到合并表(事实)的列。我有一个变更捕获表,它捕获每天记录的变更,如下所示:

CHG_TABLE:
+--------+-------------------+-----------------------+-----------+-----------+ 
|  Key   |     Start_Date    |      End_Date         |   Value   |Record_Type|
+--------+----- -------------+-----------------------+-----------+-----------+ 
| 1      |   5/25/2019  2.05 |      12/31/9999 00.00 |    800    | Insert    | 
| 1      |   5/25/2019  2.05 |      5/31/2019  11.12 |    800    | Update    | 
| 1      |   5/31/2019 11.12 |      12/31/9999 00.00 |    900    | Insert    | 
| 1      |   5/31/2019 11.12 |      6/15/2019  12.05 |    900    | Update    | 
| 1      |   6/15/2019 12.05 |      12/31/9999 00.00 |   1000    | Insert    | 
| 1      |   6/15/2019 12.05 |      6/25/2019  10.20 |   1000    | Update    | 
| 1      |   6/25/2019 10.20 |      12/31/9999 00.00 |    500    | Insert    | 
| 1      |   6/25/2019 10.20 |      6/30/2019  11.12 |    500    | Update    | 
| 1      |   6/30/2019 11.12 |      12/31/9999 00.00 |   3000    | Insert    | 
| 1      |   6/30/2019 11.12 |      7/15/2019  1.20  |   3000    | Update    | 
| 1      |   7/15/2019  1.20 |      12/31/9999 00.00 |   7000    | Insert    |
+--------+-------------------+-----------------------+-----------+-----------+

在第一次插入期间,End_Date是时间的结束。将具有新Start_Date和Value的新记录添加到源中时,它将被捕获为新条目,并且具有相同Key的先前记录将End_Date更新为新记录的Start_Date。

DIM_DATE:
+ -------- + ------------------- + -------------------- -+
| DateKey | Month_Start_Date | Month_End_Date |
+ -------- + ----- + ------------- + -------------------- -+
| 1 | 6/1/2019 | 6/30/2019 |
| 2 | 7/1/2019 | 7/31/2019 |
+ -------- + ------------------- + -------------------- -+

我正在使用DATE维度,该维度具有Month_Start_Date和Month_End_Date,因此我很挣扎。

我想从此更改表中创建每月快照,如下所示:

RESULT:
+--------+-------------------+-----------------------+-----------+-----------+
|  Key   | Month_Start_Date  |   Month_End_Date      |Begin_Value|End_Value  |
+--------+-----+-------------+-----------------------+-----------+-----------+
| 1      |   6/1/2019        |      6/30/2019        |   800     | 500       |
| 1      |   7/1/2019        |      7/31/2019        |   500     | 3000      |
+--------+-------------------+-----------------------+-----------+-----------+

Begin_Value:最大值(结束日期)<Month_Start_Date

End_Value:最大值(End_Date)<= Month_End_Date

Begin_Value应该是上个月的最新值(不是时间的结束),End_Value应该是基于Month_End_Date的最新值。

如何显示以上结果?


问题答案:

我认为您应该重新考虑一下自己的逻辑

如果CHG_TABLE在7月15日有“更新”记录,并且以后没有更改,则该新值应为7月的最终值。

假设(如果较大)是正确的,那么您应该完全忽略该END_DATE列。如果可以,请将其从数据模型中删除。不用了

而是在上创建一个降序索引CHG_TABLE.START_DATE,如下所示:

create index chg_table_n1 on chg_table (start_date desc);

然后,您应该能够像这样高效地创建快照:

select ct.key, 
       dd.month_start_date, 
       dd.month_end_date, 
       ( SELECT value
         FROM   chg_table ct2 
         WHERE  ct2.key = ct.key 
         AND    ct2.start_date < dd.month_start_date
         ORDER BY ct2.start_date DESC
         FETCH FIRST 1 ROW ONLY ) first_value,
       max(ct.value) keep ( dense_rank last order by ct.start_date ) last_value
from   dim_date dd
INNER JOIN chg_table ct ON ct.start_date BETWEEN dd.month_start_date and dd.month_end_date
GROUP BY ct.key, dd.month_start_date, dd.month_end_date;

希望您使用的是12.1或更高版本的FETCH FIRST语法。否则,您需要将该部分调整为12.1之前的版本。

带有测试数据的完整示例

WITH chg_table ( key, start_date, end_date, value, record_type ) AS
( 
SELECT 1,TO_DATE('5/25/2019  2.05','MM/DD/YYYY HH24.MI'),TO_DATE('12/31/9999 00.00','MM/DD/YYYY HH24.MI'), 800, 'Insert' FROM DUAL UNION ALL
SELECT 1,TO_DATE('5/25/2019  2.05','MM/DD/YYYY HH24.MI'),TO_DATE('5/31/2019  11.12','MM/DD/YYYY HH24.MI'), 800, 'Update' FROM DUAL UNION ALL
SELECT 1,TO_DATE('5/31/2019 11.12','MM/DD/YYYY HH24.MI'),TO_DATE('12/31/9999 00.00','MM/DD/YYYY HH24.MI'), 900, 'Insert' FROM DUAL UNION ALL
SELECT 1,TO_DATE('5/31/2019 11.12','MM/DD/YYYY HH24.MI'),TO_DATE('6/15/2019  12.05','MM/DD/YYYY HH24.MI'), 900, 'Update' FROM DUAL UNION ALL
SELECT 1,TO_DATE('6/15/2019 12.05','MM/DD/YYYY HH24.MI'),TO_DATE('12/31/9999 00.00','MM/DD/YYYY HH24.MI'), 1000, 'Insert' FROM DUAL UNION ALL
SELECT 1,TO_DATE('6/15/2019 12.05','MM/DD/YYYY HH24.MI'),TO_DATE('6/25/2019  10.20','MM/DD/YYYY HH24.MI'), 1000, 'Update' FROM DUAL UNION ALL
SELECT 1,TO_DATE('6/25/2019 10.20','MM/DD/YYYY HH24.MI'),TO_DATE('12/31/9999 00.00','MM/DD/YYYY HH24.MI'), 500, 'Insert' FROM DUAL UNION ALL
SELECT 1,TO_DATE('6/25/2019 10.20','MM/DD/YYYY HH24.MI'),TO_DATE('6/30/2019  11.12','MM/DD/YYYY HH24.MI'), 500, 'Update' FROM DUAL UNION ALL
SELECT 1,TO_DATE('6/30/2019 11.12','MM/DD/YYYY HH24.MI'),TO_DATE('12/31/9999 00.00','MM/DD/YYYY HH24.MI'),3000, 'Insert' FROM DUAL UNION ALL
SELECT 1,TO_DATE('6/30/2019 11.12','MM/DD/YYYY HH24.MI'),TO_DATE('7/15/2019  1.20','MM/DD/YYYY HH24.MI'), 3000, 'Update' FROM DUAL UNION ALL
SELECT 1,TO_DATE('7/15/2019  1.20','MM/DD/YYYY HH24.MI'),TO_DATE('12/31/9999 00.00','MM/DD/YYYY HH24.MI'),7000, 'Insert' FROM DUAL ),
dim_date ( datekey, month_start_date, month_end_date ) AS (
SELECT 1, DATE'2019-05-01', DATE'2019-06-01' - INTERVAL '1' SECOND FROM DUAL UNION ALL
SELECT 2, DATE'2019-06-01', DATE'2019-07-01' - INTERVAL '1' SECOND FROM DUAL UNION ALL
SELECT 3, DATE'2019-07-01', DATE'2019-08-01' - INTERVAL '1' SECOND FROM DUAL )
select ct.key, 
       dd.month_start_date, 
       dd.month_end_date, 
       ( SELECT value
         FROM   chg_table ct2 
         WHERE  ct2.key = ct.key 
         AND    ct2.start_date < dd.month_start_date
         ORDER BY ct2.start_date DESC
         FETCH FIRST 1 ROW ONLY ) first_value,
       max(ct.value) keep ( dense_rank last order by ct.start_date ) last_value
from   dim_date dd
INNER JOIN chg_table ct ON ct.start_date BETWEEN dd.month_start_date and dd.month_end_date
GROUP BY ct.key, dd.month_start_date, dd.month_end_date;
+-----+------------------+----------------+-------------+------------+
| KEY | MONTH_START_DATE | MONTH_END_DATE | FIRST_VALUE | LAST_VALUE |
+-----+------------------+----------------+-------------+------------+
|   1 | 01-MAY-19        | 31-MAY-19      |             |        900 |
|   1 | 01-JUN-19        | 30-JUN-19      |         900 |       3000 |
|   1 | 01-JUL-19        | 31-JUL-19      |        3000 |       7000 |
+-----+------------------+----------------+-------------+------------+

更新-假设存在DIM_PERSON表,则不带MAX().. KEEP()版本

select k.key, 
       dd.month_start_date, 
       dd.month_end_date, 
       ( SELECT value
         FROM   chg_table ct2 
         WHERE  ct2.key = k.key 
         AND    ct2.start_date < dd.month_start_date
         ORDER BY ct2.start_date DESC
         FETCH FIRST 1 ROW ONLY ) first_value,
       ( SELECT value
         FROM   chg_table ct2 
         WHERE  ct2.key = k.key 
         AND    ct2.start_date <= dd.month_end_date
         ORDER BY ct2.start_date DESC
         FETCH FIRST 1 ROW ONLY ) last_value
from   dim_date dd
CROSS JOIN  dim_person k
GROUP BY k.key, dd.month_start_date, dd.month_end_date;


 类似资料:
  • 似乎不能处理一个数字的月份中的某一天: 在此示例中,正确解析日期,但引发异常。如果我使用零填充日期,例如“05/03/1969”,则两者都起作用。但是,如果每月的日期或每年的月份都是个位数,则将引发异常。 什么是格式来解析一个数字和两位数的月份和一年中的月份?

  • 问题内容: 我正在尝试在Pandas DataFrame中每天对一些数据进行重新采样。我是熊猫的新手,也许我需要先格式化日期和时间,然后才能执行此操作,但是我找不到关于如何使用导入的时间序列数据的正确方法的良好教程。我发现的一切都是自动从Yahoo或Quandl导入数据。 这是我的DataFrame中的内容:dataframe 段屏幕截图 这是我用来创建DataFrame的代码: 有人可以帮助我了

  • 我正在使用JQuery阻止一些日期,但下个月是可用的。一个用户可以点击今天+5,所有其他的都应该被禁用。我做错了什么?

  • 我们要求每个月1日(时间: 00:00:00 AM)准确地运行一个作业。 我们使用Spring框架的计划时间任务来使用延迟和周期属性来计划作业。此类不支持在特定日期运行作业。 有人能建议我们如何使用Spring和Java技术解决这个问题吗?

  • 问题内容: 我有一张表,如下所示: 我从中创建以下视图: 现在,当我想创建每月计数以了解如何将每日总和除以得出平均列a(即特定月份中的天数)时,就会出现问题。 我知道要在PostgreSQL中获得成功,您可以: 但是我不能使用,我必须以某种方式让它知道分组完成的月份。任何建议,即什么应该取代 ??? 在此视图中: 问题答案: 更快,更短一点,您得到的是天数,而不是: 可以将多个单位合并为一个值。因

  • 我有大量的日期范围,如下所示,示例如下。我需要计算每个实际日历年有多少个月。因此,这将分解为: 合同:123 开始日期:2016年11月1日 结束日期:2018年6月1日 2016年11月1日 合同:456 开始日期:2017年5月31日 结束日期:2019年6月1日 2017年5月31日 有人知道解决这个问题的方法吗?每个合同都有一行,都在同一个表中,开始和结束日期列在同一行中。 我原本打算沿着