I struggled with this problem for several days, and now I am turning to the masses for help.
My problem is similar, but not quite the same as the previous solution on this site: PL / SQL Split, add the date to the new dates according to the maturity dates! This solution is pretty logical (include / exclude), while my problem includes some of them, as well as merging.
Although I like to think that I have an intermediate / advanced understanding of SQL + PL / SQL ... Oracle Analytic functions seem to scare my mind. I tried to read / study, but my time is running out.
Since I'm not sure about the legality of exchanging table names (COTS), business directions, etc., I am going to imitate my problem with a vague script / context. I hope this affects the spirit of the lawyer.
To the problem: I have a table that stores the history of the client. A client can come and go, and therefore we can have several rows in this table (for each client).
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;
I also have a table that contains information about attributes by range. A client can have several types of attributes at the same time and each type several times for different time intervals.
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, 'POWER' AS atb_cd, 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, 0 AS per_gal FROM DUAL UNION SELECT 1 AS cust_id, 'POWER' AS atb_cd, TO_DATE('01-JUN-2010') AS atb_start_dt, TO_DATE('30-SEP-2010') AS atb_end_dt, 'LocalNuke' AS provider, 1.70 AS per_kwh, 0 AS per_gal FROM DUAL UNION SELECT 1 AS cust_id, 'POWER' AS atb_cd, 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, 0 AS per_gal FROM DUAL UNION SELECT 1 AS cust_id, 'WATER' AS atb_cd, TO_DATE('01-MAR-2010') AS atb_start_dt, TO_DATE('31-DEC-9999') AS atb_end_dt, 'GlacialGold' AS provider, 0 AS per_kwh, 0.60 AS per_gal FROM DUAL;
Intentional data habits, I tried to make this scenario as real as I could without contacting the "real world."
The result should restrain customer activity with the help of this fictitious company and split all overlapping dates to form a timeline. Data elements must be combined for reporting.
Visually:
Cust: |----------------------| |------------------------| Power: |-------------| |--| |-------| |----------------------> Water: |------------------------------------------------------> Expected Result: |----|----|--|----|----| |----|-------------------|
The solution must be scalable to include other attributes. In the end, I would get this denormalized information in a table so that I can report customer data at any given time. For example, if they had activity, power and water on a specific day; I should be able to export per_kwh, per_gal and activity data for this day.
Output example (tabular):
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
I wrote something about 2 years ago (when this requirement looked like just Activity / Power) using 2 asynchronous cursors that handle slow deceleration (line by line).
While performance is important, the biggest reason I'm trying to find a direct / bulk sql solution is maintenance. The nested if / else cursor of my original solution is already difficult to execute and will be exponentially worse with at least two more βattributeβ intervals for separation.
I would be grateful for any help that any of you can provide.