如何将多个日期跨度合并/拆分为一个时间轴(Oracle 11g)?
几天来我一直在努力解决这个问题,现在我转向群众寻求帮助. 我的问题与此网站上的先前解决方案类似,但不完全相同: 虽然我觉得我对SQL PL / SQL有中级/高级的掌握…但Oracle Analytic函数显然让我感到困惑.我一直在努力阅读/学习,但我已经没时间了. 由于我不确定共享表名(COTS),业务线等的合法性,我将用模糊的场景/上下文来模仿我的问题.希望这能够抵御律师的精神. 关于问题: CREATE TABLE activity AS SELECT 1 AS cust_id,TO_DATE('01-JAN-2010') AS start_dt,TO_DATE('31-JUL-2010') AS end_dt,'EAST' AS region FROM DUAL UNION SELECT 1 AS cust_id,TO_DATE('01-FEB-2011') AS start_dt,TO_DATE('31-DEC-2011') AS end_dt,'EAST' AS region FROM DUAL; 我还有一个表格,其中包含跨度的属性信息.客户可以同时拥有多个属性类型,每种类型可以多次使用不同的时间跨度. CREATE TABLE attrib AS SELECT 1 AS cust_id,'POWER' AS atb_cd,TO_DATE('01-JAN-2009') AS atb_start_dt,TO_DATE('31-JAN-2010') AS atb_end_dt,'LocalNuke' AS provider,1.80 AS per_kwh,0 AS per_gal FROM DUAL UNION SELECT 1 AS cust_id,TO_DATE('01-MAR-2010') AS atb_start_dt,TO_DATE('31-MAR-2010') AS atb_end_dt,'CoalGuys' AS provider,1.60 AS per_kwh,TO_DATE('01-JUN-2010') AS atb_start_dt,TO_DATE('30-SEP-2010') AS atb_end_dt,1.70 AS per_kwh,TO_DATE('01-MAR-2011') AS atb_start_dt,TO_DATE('31-DEC-9999') AS atb_end_dt,'GeoHeat' AS provider,1.10 AS per_kwh,'WATER' AS atb_cd,'GlacialGold' AS provider,0 AS per_kwh,0.60 AS per_gal FROM DUAL; 数据奇怪是有意的,我试图将这个场景尽可能地变为现实世界而不与“现实世界”相关. 结果应该限制客户与这家虚构公司的活动的跨度,并将所有重叠日期分开以形成时间表.需要将数据元素合并在一起以进行报告. 视觉: Cust: |----------------------| |------------------------| Power: |-------------| |--| |-------| |----------------------> Water: |------------------------------------------------------> Expected Result: |----|----|--|----|----| |----|-------------------| 解决方案应该是可扩展的,以包括其他属性.最后,我在表格中有这种非规范化信息,这样我就可以在任何时间点报告客户的数据.例如,如果他们在某一天有活动,权力和水;我应该能够导出当天的per_kwh,per_gal和活动数据. 示例输出(表格): CUST_ID FROM_DT THRU_DT REGION POWER_PROVIDER WATER_PROVIDER PER_KWH PER_GAL ------- ----------- ----------- ------ -------------- -------------- ------- ------- 1 01-JAN-2010 31-JAN-2010 EAST LocalNuke 1.80 0 1 01-FEB-2010 28-FEB-2010 EAST 0 0 1 01-MAR-2010 31-MAR-2010 EAST CoalGuys GlacialGold 1.60 0.60 1 01-APR-2010 31-MAY-2010 EAST GlacialGold 0 0.60 1 01-JUN-2010 31-JUL-2010 EAST LocalNuke GlacialGold 1.70 0.60 1 01-FEB-2011 28-FEB-2011 EAST GlacialGold 0 0.60 1 01-MAR-2011 31-DEC-2011 EAST GeoHeat GlacialGold 1.10 0.60 我在2年前写了一些东西(当需求类似于Activity / Power时),使用2个异步游标逐慢处理(逐行). 虽然性能很重要,但我试图找到直接/批量sql解决方案的最大原因是维护.我的原始解决方案的if / else光标嵌套已经难以遵循,并且至少还有2个“属性”跨度要分裂,指数会更糟. 如果您能提供任何帮助,我将不胜感激. 解决方法这可能有效.它不会将连续的区域合并在一起,但它仍然应该完成工作.WITH milestone AS ( SELECT cust_id,start_dt AS point_in_time FROM ACTIVITY UNION SELECT cust_id,atb_start_dt AS point_in_time FROM ATTRIB UNION SELECT cust_id,LEAST(end_dt,TO_DATE('30-DEC-9999')) + 1 AS point_in_time FROM ACTIVITY UNION SELECT cust_id,LEAST(atb_end_dt,TO_DATE('30-DEC-9999')) + 1 AS point_in_time FROM ATTRIB ) SELECT milestone.cust_id AS cust_id,milestone.point_in_time AS from_dt,LEAD(point_in_time) OVER (PARTITION BY milestone.cust_id ORDER BY milestone.point_in_time) - 1 AS thru_dt,activity.region AS region,power_attrib.provider AS power_provider,water_attrib.provider AS water_provider,COALESCE(power_attrib.per_kwh,0) AS per_kwh,COALESCE(water_attrib.per_gal,0) AS per_gal FROM MILESTONE LEFT OUTER JOIN ACTIVITY ON milestone.cust_id = activity.cust_id AND milestone.point_in_time BETWEEN activity.start_dt AND activity.end_dt LEFT OUTER JOIN ATTRIB power_attrib ON milestone.cust_id = power_attrib.cust_id AND power_attrib.atb_cd = 'POWER' AND milestone.point_in_time BETWEEN power_attrib.atb_start_dt AND power_attrib.atb_end_dt LEFT OUTER JOIN ATTRIB water_attrib ON milestone.cust_id = water_attrib.cust_id AND water_attrib.atb_cd = 'WATER' AND milestone.point_in_time BETWEEN water_attrib.atb_start_dt AND water_attrib.atb_end_dt (编辑:晋中站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |