{"id":355,"date":"2012-12-27T16:05:24","date_gmt":"2012-12-27T15:05:24","guid":{"rendered":"http:\/\/www.salvis.com\/blog\/?p=355"},"modified":"2023-11-08T20:02:18","modified_gmt":"2023-11-08T19:02:18","slug":"merging-temporal-intervals-with-gaps","status":"publish","type":"post","link":"https:\/\/www.salvis.com\/blog\/2012\/12\/27\/merging-temporal-intervals-with-gaps\/","title":{"rendered":"Merging Temporal Intervals with Gaps"},"content":{"rendered":"\n<p>In&nbsp;<a title=\"Joining Temporal Intervals\" href=\"\/\/www.salvis.com\/blog\/2012\/12\/24\/joining-temporal-intervals\/\">Joining Temporal Intervals<\/a> I explained how to join multiple temporal tables. The provided solution merges also temporal intervals but &#8211; as pointed out in that post &#8211; may produce wrong results if the underlying driving table is not gaplessly historized. In this post, I&#8217;ll explain how to merge temporal intervals with various data constellations correctly.<\/p>\n\n\n\n<p>You find the scripts to create and populate the tables for scenarios A and B <a href=\"\/\/www.salvis.com\/blog\/wp-content\/uploads\/2012\/12\/SetupDataForMergingTemporalIntervals.sql_1.txt\">here<\/a>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Scenario A &#8211; No overlapping intervals<\/h3>\n\n\n\n<p>This scenario handles consistent data. This means no overlapping intervals, no duplicate intervals, no including intervals, and no negative intervals (valid_to &lt; valid_from). Here is the content of the example table t1:<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7\">Test Data Set t1<\/span><span role=\"button\" tabindex=\"0\" data-code=\"SQL&gt; SELECT * FROM t1;\n\n       VID        OID VALID_FROM  VALID_TO    C1         C2\n---------- ---------- ----------- ----------- ---------- ----------\n         1          1 01-JAN-2010 31-DEC-2010 A          B1\n         2          1 01-JAN-2011 31-MAR-2011 A          B2\n         3          1 01-JUN-2011 31-JAN-2012 A          B2\n         4          1 01-APR-2012 31-DEC-9999 A          B4\n         5          2 01-JAN-2010 31-JUL-2012 B          B1\n         6          2 01-AUG-2012 31-DEC-9999 B          B2\n        18          4 01-JAN-2010 30-SEP-2011 D          D1\n        19          4 01-OCT-2011 30-SEP-2012            D2\n        20          4 01-OCT-2012 31-DEC-9999 D          D3\" style=\"color:#D4D4D4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dark-plus\" style=\"background-color: #1E1E1E\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #D4D4D4\">SQL&gt; SELECT * FROM t1;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\"><\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">       VID        OID VALID_FROM  VALID_TO    C1         C2<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">---------- ---------- ----------- ----------- ---------- ----------<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">         1          1 01-JAN-2010 31-DEC-2010 A          B1<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">         2          1 01-JAN-2011 31-MAR-2011 A          B2<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">         3          1 01-JUN-2011 31-JAN-2012 A          B2<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">         4          1 01-APR-2012 31-DEC-9999 A          B4<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">         5          2 01-JAN-2010 31-JUL-2012 B          B1<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">         6          2 01-AUG-2012 31-DEC-9999 B          B2<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        18          4 01-JAN-2010 30-SEP-2011 D          D1<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        19          4 01-OCT-2011 30-SEP-2012            D2<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        20          4 01-OCT-2012 31-DEC-9999 D          D3<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>I&#8217;d like to write a query which produces all intervals for the columns OID and C1 honoring gaps in the historization. For OID 1 I expect that records 1 and 2 are merged, but records 3 and 4 are not merged because the intervals are not &#8220;connected&#8221;. For OID 2 I expected to get a single merged interval. For OID 4 I expect to get 3 records since the records with C1=&#8217;D&#8217; are not connected.<\/p>\n\n\n\n<p>So, the following query result is expected:<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7\">Expected Result<\/span><span role=\"button\" tabindex=\"0\" data-code=\"       OID VALID_FROM  VALID_TO    C1\n---------- ----------- ----------- ----------\n         1 01-JAN-2010 31-MAR-2011 A\n         1 01-JUN-2011 31-JAN-2012 A\n         1 01-APR-2012 31-DEC-9999 A\n         2 01-JAN-2010 31-DEC-9999 B\n         4 01-JAN-2010 30-SEP-2011 D\n         4 01-OCT-2011 30-SEP-2012\n         4 01-OCT-2012 31-DEC-9999 D\" style=\"color:#D4D4D4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dark-plus\" style=\"background-color: #1E1E1E\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #D4D4D4\">       OID VALID_FROM  VALID_TO    C1<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">---------- ----------- ----------- ----------<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">         1 01-JAN-2010 31-MAR-2011 A<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">         1 01-JUN-2011 31-JAN-2012 A<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">         1 01-APR-2012 31-DEC-9999 A<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">         2 01-JAN-2010 31-DEC-9999 B<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">         4 01-JAN-2010 30-SEP-2011 D<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">         4 01-OCT-2011 30-SEP-2012<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">         4 01-OCT-2012 31-DEC-9999 D<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>The next query produces exactly this result.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7\">Query to Merge Non-Overlapping Intervals<\/span><span role=\"button\" tabindex=\"0\" data-code=\"WITH\n   calc_various AS (\n      -- produces column has_gap with the following meaning:\n      -- 1: offset &gt; 0 between current and previous record (gap)\n      -- 0: offset = 0 between current and previous record (no gap)\n      -- produces column new_group with the following meaning:\n      -- 1: group-by-columns differ in current and previous record\n      -- 0: same group-by-columns in current and previous record\n      SELECT oid,\n             valid_from,\n             valid_to,\n             c1,\n             c2,\n             CASE\n                WHEN LAG(valid_to, 1, valid_from - 1) OVER(\n                        PARTITION BY oid ORDER BY valid_from\n                     ) = valid_from - 1 THEN\n                   0\n                ELSE\n                   1\n             END AS has_gap,\n             CASE\n                WHEN LAG(c1, 1, c1) OVER(\n                        PARTITION BY oid ORDER BY valid_from\n                     ) = c1 THEN\n                   0\n                ELSE\n                   1\n             END AS new_group\n        FROM t1\n   ),\n   calc_group AS (\n      -- produces column group_no, records with the same group_no\n      -- are mergeable, group_no is calculated per oid \n      SELECT oid,\n             valid_from,\n             valid_to,\n             c1,\n             c2,\n             SUM(has_gap + new_group) OVER(\n                PARTITION BY oid ORDER BY oid, valid_from\n             ) AS group_no\n        FROM calc_various\n   ),\n   merged AS (\n      -- produces the final merged result\n      -- grouping by group_no ensures that gaps are honored\n      SELECT oid,\n             MIN(valid_from) AS valid_from,\n             MAX(valid_to) AS valid_to,\n             c1\n        FROM calc_group\n       GROUP BY oid, c1, group_no\n       ORDER BY oid, valid_from\n   )\n-- main \nSELECT * FROM merged;\" style=\"color:#D4D4D4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dark-plus\" style=\"background-color: #1E1E1E\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #569CD6\">WITH<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">   calc_various <\/span><span style=\"color: #569CD6\">AS<\/span><span style=\"color: #D4D4D4\"> (<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">      <\/span><span style=\"color: #6A9955\">-- produces column has_gap with the following meaning:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">      <\/span><span style=\"color: #6A9955\">-- 1: offset &gt; 0 between current and previous record (gap)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">      <\/span><span style=\"color: #6A9955\">-- 0: offset = 0 between current and previous record (no gap)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">      <\/span><span style=\"color: #6A9955\">-- produces column new_group with the following meaning:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">      <\/span><span style=\"color: #6A9955\">-- 1: group-by-columns differ in current and previous record<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">      <\/span><span style=\"color: #6A9955\">-- 0: same group-by-columns in current and previous record<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">      <\/span><span style=\"color: #569CD6\">SELECT<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">oid<\/span><span style=\"color: #D4D4D4\">,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">             valid_from,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">             valid_to,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">             c1,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">             c2,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">             <\/span><span style=\"color: #569CD6\">CASE<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">                <\/span><span style=\"color: #569CD6\">WHEN<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #DCDCAA\">LAG<\/span><span style=\"color: #D4D4D4\">(valid_to, <\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">, valid_from - <\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">) <\/span><span style=\"color: #569CD6\">OVER<\/span><span style=\"color: #D4D4D4\">(<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">                        <\/span><span style=\"color: #569CD6\">PARTITION<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">BY<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">oid<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">ORDER BY<\/span><span style=\"color: #D4D4D4\"> valid_from<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">                     ) = valid_from - <\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">THEN<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">                   <\/span><span style=\"color: #B5CEA8\">0<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">                <\/span><span style=\"color: #569CD6\">ELSE<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">                   <\/span><span style=\"color: #B5CEA8\">1<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">             <\/span><span style=\"color: #569CD6\">END<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">AS<\/span><span style=\"color: #D4D4D4\"> has_gap,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">             <\/span><span style=\"color: #569CD6\">CASE<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">                <\/span><span style=\"color: #569CD6\">WHEN<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #DCDCAA\">LAG<\/span><span style=\"color: #D4D4D4\">(c1, <\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">, c1) <\/span><span style=\"color: #569CD6\">OVER<\/span><span style=\"color: #D4D4D4\">(<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">                        <\/span><span style=\"color: #569CD6\">PARTITION<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">BY<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">oid<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">ORDER BY<\/span><span style=\"color: #D4D4D4\"> valid_from<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">                     ) = c1 <\/span><span style=\"color: #569CD6\">THEN<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">                   <\/span><span style=\"color: #B5CEA8\">0<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">                <\/span><span style=\"color: #569CD6\">ELSE<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">                   <\/span><span style=\"color: #B5CEA8\">1<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">             <\/span><span style=\"color: #569CD6\">END<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">AS<\/span><span style=\"color: #D4D4D4\"> new_group<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #569CD6\">FROM<\/span><span style=\"color: #D4D4D4\"> t1<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">   ),<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">   calc_group <\/span><span style=\"color: #569CD6\">AS<\/span><span style=\"color: #D4D4D4\"> (<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">      <\/span><span style=\"color: #6A9955\">-- produces column group_no, records with the same group_no<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">      <\/span><span style=\"color: #6A9955\">-- are mergeable, group_no is calculated per oid <\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">      <\/span><span style=\"color: #569CD6\">SELECT<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">oid<\/span><span style=\"color: #D4D4D4\">,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">             valid_from,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">             valid_to,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">             c1,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">             c2,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">             <\/span><span style=\"color: #DCDCAA\">SUM<\/span><span style=\"color: #D4D4D4\">(has_gap + new_group) <\/span><span style=\"color: #569CD6\">OVER<\/span><span style=\"color: #D4D4D4\">(<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">                <\/span><span style=\"color: #569CD6\">PARTITION<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">BY<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">oid<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">ORDER BY<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">oid<\/span><span style=\"color: #D4D4D4\">, valid_from<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">             ) <\/span><span style=\"color: #569CD6\">AS<\/span><span style=\"color: #D4D4D4\"> group_no<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #569CD6\">FROM<\/span><span style=\"color: #D4D4D4\"> calc_various<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">   ),<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">   merged <\/span><span style=\"color: #569CD6\">AS<\/span><span style=\"color: #D4D4D4\"> (<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">      <\/span><span style=\"color: #6A9955\">-- produces the final merged result<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">      <\/span><span style=\"color: #6A9955\">-- grouping by group_no ensures that gaps are honored<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">      <\/span><span style=\"color: #569CD6\">SELECT<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">oid<\/span><span style=\"color: #D4D4D4\">,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">             <\/span><span style=\"color: #DCDCAA\">MIN<\/span><span style=\"color: #D4D4D4\">(valid_from) <\/span><span style=\"color: #569CD6\">AS<\/span><span style=\"color: #D4D4D4\"> valid_from,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">             <\/span><span style=\"color: #DCDCAA\">MAX<\/span><span style=\"color: #D4D4D4\">(valid_to) <\/span><span style=\"color: #569CD6\">AS<\/span><span style=\"color: #D4D4D4\"> valid_to,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">             c1<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #569CD6\">FROM<\/span><span style=\"color: #D4D4D4\"> calc_group<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">       <\/span><span style=\"color: #569CD6\">GROUP BY<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">oid<\/span><span style=\"color: #D4D4D4\">, c1, group_no<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">       <\/span><span style=\"color: #569CD6\">ORDER BY<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">oid<\/span><span style=\"color: #D4D4D4\">, valid_from<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">   )<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">-- main <\/span><\/span>\n<span class=\"line\"><span style=\"color: #569CD6\">SELECT<\/span><span style=\"color: #D4D4D4\"> * <\/span><span style=\"color: #569CD6\">FROM<\/span><span style=\"color: #D4D4D4\"> merged;<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>The usability of the WITH clause aka Subquery Factoring Clause improved significantly with 11gR2. Since then it&#8217;s not necessary to reference all named queries anymore. The named queries become real transient views and this simplifies debugging a lot. &#8211; If you replace the content of line 57 with &#8220;SELECT * FROM calc_various ORDER BY oid, valid_from;&#8221; the query produces the following result:<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7\">Result of calc_various<\/span><span role=\"button\" tabindex=\"0\" data-code=\"OID VALID_FROM  VALID_TO    C1 C2 HAS_GAP NEW_GROUP\n--- ----------- ----------- -- -- ------- ---------\n  1 01-JAN-2010 31-DEC-2010 A  B1       0         0\n  1 01-JAN-2011 31-MAR-2011 A  B2       0         0\n  1 01-JUN-2011 31-JAN-2012 A  B2       1         0\n  1 01-APR-2012 31-DEC-9999 A  B4       1         0\n  2 01-JAN-2010 31-JUL-2012 B  B1       0         0\n  2 01-AUG-2012 31-DEC-9999 B  B2       0         0\n  4 01-JAN-2010 30-SEP-2011 D  D1       0         0\n  4 01-OCT-2011 30-SEP-2012    D2       0         1\n  4 01-OCT-2012 31-DEC-9999 D  D3       0         1\" style=\"color:#D4D4D4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dark-plus\" style=\"background-color: #1E1E1E\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #D4D4D4\">OID VALID_FROM  VALID_TO    C1 C2 HAS_GAP NEW_GROUP<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">--- ----------- ----------- -- -- ------- ---------<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">  1 01-JAN-2010 31-DEC-2010 A  B1       0         0<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">  1 01-JAN-2011 31-MAR-2011 A  B2       0         0<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">  1 01-JUN-2011 31-JAN-2012 A  B2       1         0<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">  1 01-APR-2012 31-DEC-9999 A  B4       1         0<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">  2 01-JAN-2010 31-JUL-2012 B  B1       0         0<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">  2 01-AUG-2012 31-DEC-9999 B  B2       0         0<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">  4 01-JAN-2010 30-SEP-2011 D  D1       0         0<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">  4 01-OCT-2011 30-SEP-2012    D2       0         1<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">  4 01-OCT-2012 31-DEC-9999 D  D3       0         1<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>You see that the value 1 for HAS_GAP indicates that the record is not &#8220;connected&#8221; with the previous record. Additionally, the value 1 for the column NEW_GROUP indicates that the records must not be merged even if they are connected.<\/p>\n\n\n\n<p>To simplify the calculation of NEW_GROUP for multiple group by columns (used in the named query &#8220;merged&#8221;) build a concatenated string of all relevant columns to deal with a single column similar to column C1 in this example.<\/p>\n\n\n\n<p>HAS_GAP and NEW_GROUP are used in the subsequent named query calc_group which produces the following result:<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7\">Result of calc_group<\/span><span role=\"button\" tabindex=\"0\" data-code=\"OID VALID_FROM  VALID_TO    C1 C2 GROUP_NO\n--- ----------- ----------- -- -- --------\n  1 01-JAN-2010 31-DEC-2010 A  B1        0\n  1 01-JAN-2011 31-MAR-2011 A  B2        0\n  1 01-JUN-2011 31-JAN-2012 A  B2        1\n  1 01-APR-2012 31-DEC-9999 A  B4        2\n  2 01-JAN-2010 31-JUL-2012 B  B1        0\n  2 01-AUG-2012 31-DEC-9999 B  B2        0\n  4 01-JAN-2010 30-SEP-2011 D  D1        0\n  4 01-OCT-2011 30-SEP-2012    D2        1\n  4 01-OCT-2012 31-DEC-9999 D  D3        2\" style=\"color:#D4D4D4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dark-plus\" style=\"background-color: #1E1E1E\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #D4D4D4\">OID VALID_FROM  VALID_TO    C1 C2 GROUP_NO<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">--- ----------- ----------- -- -- --------<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">  1 01-JAN-2010 31-DEC-2010 A  B1        0<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">  1 01-JAN-2011 31-MAR-2011 A  B2        0<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">  1 01-JUN-2011 31-JAN-2012 A  B2        1<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">  1 01-APR-2012 31-DEC-9999 A  B4        2<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">  2 01-JAN-2010 31-JUL-2012 B  B1        0<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">  2 01-AUG-2012 31-DEC-9999 B  B2        0<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">  4 01-JAN-2010 30-SEP-2011 D  D1        0<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">  4 01-OCT-2011 30-SEP-2012    D2        1<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">  4 01-OCT-2012 31-DEC-9999 D  D3        2<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>The GROUP_NO is calculated per OID. It&#8217;s technically a running total of HAS_GAP + NEW_GROUP. All intervals with the same GROUP_NO are mergeable. E.g. record 2, 3 and 4 have a different GROUP_NO which ensures that every single gap is honored for OID 1.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Scenario B &#8211; With Overlapping intervals<\/h3>\n\n\n\n<p>The reality is that we have sometimes to deal with inconsistent data. E.g. duplicate data intervals, overlapping data intervals or even negative data intervals (valid_to &lt; valid_from). I&#8217;ve created an example table t2 which is in fact a copy of t1 but includes an additional messy OID 3 with the following data:<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7\">Test Data Set t2<\/span><span role=\"button\" tabindex=\"0\" data-code=\"SQL&gt; SELECT * FROM t2 WHERE oid &gt;= 3 ORDER BY vid;\n\n       VID        OID VALID_FROM  VALID_TO    C1         C2\n---------- ---------- ----------- ----------- ---------- ----------\n         7          3 01-JAN-2010 31-DEC-2010 C          B1\n         8          3 01-JAN-2010 31-MAR-2010 C          B2\n         9          3 01-JUN-2010 31-AUG-2010 C          B3\n        10          3 01-OCT-2010 31-DEC-2010 C          B4\n        11          3 01-FEB-2011 30-JUN-2011 C          B5\n        12          3 01-FEB-2011 30-JUN-2011 C          B6\n        13          3 01-JUN-2011 31-AUG-2011 C          B7\n        14          3 31-AUG-2011 30-SEP-2011 C          B8\n        15          3 01-DEC-2011 31-MAY-2012 C          B9\n        16          3 01-DEC-2011 31-MAY-2012 C          B9\n        17          3 01-JUN-2012 31-DEC-2012 C          B10\" style=\"color:#D4D4D4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dark-plus\" style=\"background-color: #1E1E1E\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #D4D4D4\">SQL&gt; SELECT * FROM t2 WHERE oid &gt;= 3 ORDER BY vid;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\"><\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">       VID        OID VALID_FROM  VALID_TO    C1         C2<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">---------- ---------- ----------- ----------- ---------- ----------<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">         7          3 01-JAN-2010 31-DEC-2010 C          B1<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">         8          3 01-JAN-2010 31-MAR-2010 C          B2<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">         9          3 01-JUN-2010 31-AUG-2010 C          B3<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        10          3 01-OCT-2010 31-DEC-2010 C          B4<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        11          3 01-FEB-2011 30-JUN-2011 C          B5<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        12          3 01-FEB-2011 30-JUN-2011 C          B6<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        13          3 01-JUN-2011 31-AUG-2011 C          B7<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        14          3 31-AUG-2011 30-SEP-2011 C          B8<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        15          3 01-DEC-2011 31-MAY-2012 C          B9<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        16          3 01-DEC-2011 31-MAY-2012 C          B9<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        17          3 01-JUN-2012 31-DEC-2012 C          B10<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>The following figure visualizes the intervals of OID 3. The green patterns are expected to be used and the red patterns are expected to be ignored. The rationale is that the VID (version ID) is typically based on an Oracle Sequence and therefore it&#8217;s assumed that higher VIDs are newer and therefore more adequate. In real cases, you may have additional information such as created_at or modified_on timestamps which helps you identify the record to be used in conflicting situations. Since data is considered inconsistent in this scenario the cleansing strategy might be very different in real cases. However, cleansing is always the first step and in this example, the highest VID has the highest priority in case of conflicts.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><a href=\"\/\/www.salvis.com\/blog\/wp-content\/uploads\/2012\/12\/MergingOverviewScenarioB1.png\"><img wpfc-lazyload-disable=\"true\" loading=\"lazy\" decoding=\"async\" width=\"749\" height=\"294\" src=\"\/\/www.salvis.com\/blog\/wp-content\/uploads\/2012\/12\/MergingOverviewScenarioB1.png\" alt=\"MergingOverviewScenarioB\" class=\"wp-image-766\" srcset=\"https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2012\/12\/MergingOverviewScenarioB1.png 749w, https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2012\/12\/MergingOverviewScenarioB1-300x117.png 300w\" sizes=\"auto, (max-width:767px) 480px, 749px\" \/><\/a><\/figure>\n\n\n\n<p>In cleansing step 1 we gather all potential starting intervals. We do not need all these intervals, but since we will merge intervals in the last processing step, we do not have to care about some unnecessary intervals right now.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7\">Cleansing Step 1<\/span><span role=\"button\" tabindex=\"0\" data-code=\"SQL&gt; WITH\n  2     o AS (\n  3        -- object identifier and their valid_from values\n  4        SELECT oid, valid_from FROM t2\n  5        UNION\n  6        SELECT oid, valid_to + 1 FROM t2\n  7         WHERE valid_to != DATE '9999-12-31'\n  8     )\n  9  -- main\n 10  SELECT * FROM o WHERE oid = 3;\n\n       OID VALID_FROM\n---------- -----------\n         3 01-JAN-2010\n         3 01-APR-2010\n         3 01-JUN-2010\n         3 01-SEP-2010\n         3 01-OCT-2010\n         3 01-JAN-2011\n         3 01-FEB-2011\n         3 01-JUN-2011\n         3 01-JUL-2011\n         3 31-AUG-2011\n         3 01-SEP-2011\n         3 01-OCT-2011\n         3 01-DEC-2011\n         3 01-JUN-2012\n         3 01-JAN-2013\n\n15 rows selected.\" style=\"color:#D4D4D4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dark-plus\" style=\"background-color: #1E1E1E\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #D4D4D4\">SQL&gt; WITH<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">  2     o AS (<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">  3        -- object identifier and their valid_from values<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">  4        SELECT oid, valid_from FROM t2<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">  5        UNION<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">  6        SELECT oid, valid_to + 1 FROM t2<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">  7         WHERE valid_to != DATE &#39;9999-12-31&#39;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">  8     )<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">  9  -- main<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\"> 10  SELECT * FROM o WHERE oid = 3;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\"><\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">       OID VALID_FROM<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">---------- -----------<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">         3 01-JAN-2010<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">         3 01-APR-2010<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">         3 01-JUN-2010<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">         3 01-SEP-2010<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">         3 01-OCT-2010<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">         3 01-JAN-2011<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">         3 01-FEB-2011<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">         3 01-JUN-2011<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">         3 01-JUL-2011<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">         3 31-AUG-2011<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">         3 01-SEP-2011<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">         3 01-OCT-2011<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">         3 01-DEC-2011<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">         3 01-JUN-2012<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">         3 01-JAN-2013<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\"><\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">15 rows selected.<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>In cleansing step 2 we calculate the relevant VID for every previous result. Additionally, we may inexpensively calculate if an interval is a gap.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7\">Cleansing Step 1 and 2<\/span><span role=\"button\" tabindex=\"0\" data-code=\"SQL&gt; WITH\n  2     o AS (\n  3        -- object identifier and their valid_from values\n  4        SELECT oid, valid_from FROM t2\n  5        UNION\n  6        SELECT oid, valid_to + 1 FROM t2\n  7         WHERE valid_to != DATE '9999-12-31'\n  8     ),\n  9     v AS (\n 10        -- relevant version identifier per valid_from\n 11        -- produces column is_gap\n 12        SELECT o.oid,\n 13               MAX(vid) AS vid,\n 14               o.valid_from,\n 15               NVL2(MAX(vid), 0, 1) AS is_gap\n 16          FROM o\n 17          LEFT JOIN t2\n 18            ON t2.oid = o.oid\n 19               AND o.valid_from BETWEEN t2.valid_from AND t2.valid_to\n 20         GROUP BY o.oid, o.valid_from\n 21     )\n 22  -- main\n 23  SELECT * FROM v WHERE oid = 3 ORDER BY valid_from;\n\n       OID        VID VALID_FROM      IS_GAP\n---------- ---------- ----------- ----------\n         3          8 01-JAN-2010          0\n         3          7 01-APR-2010          0\n         3          9 01-JUN-2010          0\n         3          7 01-SEP-2010          0\n         3         10 01-OCT-2010          0\n         3            01-JAN-2011          1\n         3         12 01-FEB-2011          0\n         3         13 01-JUN-2011          0\n         3         13 01-JUL-2011          0\n         3         14 31-AUG-2011          0\n         3         14 01-SEP-2011          0\n         3            01-OCT-2011          1\n         3         16 01-DEC-2011          0\n         3         17 01-JUN-2012          0\n         3            01-JAN-2013          1\n\n15 rows selected.\" style=\"color:#D4D4D4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dark-plus\" style=\"background-color: #1E1E1E\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #D4D4D4\">SQL&gt; WITH<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">  2     o AS (<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">  3        -- object identifier and their valid_from values<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">  4        SELECT oid, valid_from FROM t2<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">  5        UNION<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">  6        SELECT oid, valid_to + 1 FROM t2<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">  7         WHERE valid_to != DATE &#39;9999-12-31&#39;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">  8     ),<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">  9     v AS (<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\"> 10        -- relevant version identifier per valid_from<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\"> 11        -- produces column is_gap<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\"> 12        SELECT o.oid,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\"> 13               MAX(vid) AS vid,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\"> 14               o.valid_from,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\"> 15               NVL2(MAX(vid), 0, 1) AS is_gap<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\"> 16          FROM o<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\"> 17          LEFT JOIN t2<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\"> 18            ON t2.oid = o.oid<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\"> 19               AND o.valid_from BETWEEN t2.valid_from AND t2.valid_to<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\"> 20         GROUP BY o.oid, o.valid_from<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\"> 21     )<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\"> 22  -- main<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\"> 23  SELECT * FROM v WHERE oid = 3 ORDER BY valid_from;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\"><\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">       OID        VID VALID_FROM      IS_GAP<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">---------- ---------- ----------- ----------<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">         3          8 01-JAN-2010          0<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">         3          7 01-APR-2010          0<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">         3          9 01-JUN-2010          0<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">         3          7 01-SEP-2010          0<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">         3         10 01-OCT-2010          0<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">         3            01-JAN-2011          1<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">         3         12 01-FEB-2011          0<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">         3         13 01-JUN-2011          0<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">         3         13 01-JUL-2011          0<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">         3         14 31-AUG-2011          0<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">         3         14 01-SEP-2011          0<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">         3            01-OCT-2011          1<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">         3         16 01-DEC-2011          0<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">         3         17 01-JUN-2012          0<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">         3            01-JAN-2013          1<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\"><\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">15 rows selected.<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>In cleansing step 3 we extend the previous result by the missing columns from table t2 and calculate the NEW_GROUP column with the same logic as in scenario A.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7\">Cleansing Step 1, 2 and 3<\/span><span role=\"button\" tabindex=\"0\" data-code=\"SQL&gt; WITH\n  2     o AS (\n  3        -- object identifier and their valid_from values\n  4        SELECT oid, valid_from FROM t2\n  5        UNION\n  6        SELECT oid, valid_to + 1 FROM t2\n  7         WHERE valid_to != DATE '9999-12-31'\n  8     ),\n  9     v AS (\n 10        -- relevant version identifier per valid_from\n 11        -- produces column is_gap\n 12        SELECT o.oid,\n 13               MAX(vid) AS vid,\n 14               o.valid_from,\n 15               NVL2(MAX(vid), 0, 1) AS is_gap\n 16          FROM o\n 17          LEFT JOIN t2\n 18            ON t2.oid = o.oid\n 19               AND o.valid_from BETWEEN t2.valid_from AND t2.valid_to\n 20         GROUP BY o.oid, o.valid_from\n 21     ),\n 22     combined AS (\n 23        -- combines previous intermediate result v with t2\n 24        -- produces the valid_to and new_group columns\n 25        SELECT t2.vid,\n 26               v.oid,\n 27               v.valid_from,\n 28               LEAD(v.valid_from - 1, 1, DATE '9999-12-31') OVER (\n 29                  PARTITION BY v.oid ORDER BY v.valid_from\n 30               ) AS valid_to,\n 31               t2.c1,\n 32               t2.c2,\n 33               v.is_gap,\n 34               CASE\n 35                  WHEN LAG(t2.c1, 1, t2.c1) OVER(\n 36                          PARTITION BY t2.oid ORDER BY t2.valid_from\n 37                       ) = c1 THEN\n 38                     0\n 39                  ELSE\n 40                     1\n 41               END AS new_group\n 42          FROM v\n 43          LEFT JOIN t2\n 44            ON t2.oid = v.oid\n 45               AND t2.vid = v.vid\n 46               AND v.valid_from BETWEEN t2.valid_from AND t2.valid_to\n 47     )\n 48  -- main\n 49  SELECT * FROM combined WHERE oid = 3 ORDER BY valid_from;\n\nVID OID VALID_FROM  VALID_TO    C1 C2  IS_GAP NEW_GROUP\n--- --- ----------- ----------- -- --- ------ ---------\n  8   3 01-JAN-2010 31-MAR-2010 C  B2       0         0\n  7   3 01-APR-2010 31-MAY-2010 C  B1       0         0\n  9   3 01-JUN-2010 31-AUG-2010 C  B3       0         0\n  7   3 01-SEP-2010 30-SEP-2010 C  B1       0         0\n 10   3 01-OCT-2010 31-DEC-2010 C  B4       0         0\n      3 01-JAN-2011 31-JAN-2011             1         1\n 12   3 01-FEB-2011 31-MAY-2011 C  B6       0         0\n 13   3 01-JUN-2011 30-JUN-2011 C  B7       0         0\n 13   3 01-JUL-2011 30-AUG-2011 C  B7       0         0\n 14   3 31-AUG-2011 31-AUG-2011 C  B8       0         0\n 14   3 01-SEP-2011 30-SEP-2011 C  B8       0         0\n      3 01-OCT-2011 30-NOV-2011             1         1\n 16   3 01-DEC-2011 31-MAY-2012 C  B9       0         0\n 17   3 01-JUN-2012 31-DEC-2012 C  B10      0         0\n      3 01-JAN-2013 31-DEC-9999             1         1\n\n15 rows selected.\" style=\"color:#D4D4D4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dark-plus\" style=\"background-color: #1E1E1E\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #D4D4D4\">SQL&gt; WITH<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">  2     o AS (<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">  3        -- object identifier and their valid_from values<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">  4        SELECT oid, valid_from FROM t2<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">  5        UNION<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">  6        SELECT oid, valid_to + 1 FROM t2<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">  7         WHERE valid_to != DATE &#39;9999-12-31&#39;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">  8     ),<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">  9     v AS (<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\"> 10        -- relevant version identifier per valid_from<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\"> 11        -- produces column is_gap<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\"> 12        SELECT o.oid,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\"> 13               MAX(vid) AS vid,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\"> 14               o.valid_from,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\"> 15               NVL2(MAX(vid), 0, 1) AS is_gap<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\"> 16          FROM o<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\"> 17          LEFT JOIN t2<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\"> 18            ON t2.oid = o.oid<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\"> 19               AND o.valid_from BETWEEN t2.valid_from AND t2.valid_to<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\"> 20         GROUP BY o.oid, o.valid_from<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\"> 21     ),<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\"> 22     combined AS (<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\"> 23        -- combines previous intermediate result v with t2<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\"> 24        -- produces the valid_to and new_group columns<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\"> 25        SELECT t2.vid,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\"> 26               v.oid,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\"> 27               v.valid_from,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\"> 28               LEAD(v.valid_from - 1, 1, DATE &#39;9999-12-31&#39;) OVER (<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\"> 29                  PARTITION BY v.oid ORDER BY v.valid_from<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\"> 30               ) AS valid_to,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\"> 31               t2.c1,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\"> 32               t2.c2,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\"> 33               v.is_gap,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\"> 34               CASE<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\"> 35                  WHEN LAG(t2.c1, 1, t2.c1) OVER(<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\"> 36                          PARTITION BY t2.oid ORDER BY t2.valid_from<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\"> 37                       ) = c1 THEN<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\"> 38                     0<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\"> 39                  ELSE<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\"> 40                     1<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\"> 41               END AS new_group<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\"> 42          FROM v<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\"> 43          LEFT JOIN t2<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\"> 44            ON t2.oid = v.oid<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\"> 45               AND t2.vid = v.vid<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\"> 46               AND v.valid_from BETWEEN t2.valid_from AND t2.valid_to<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\"> 47     )<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\"> 48  -- main<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\"> 49  SELECT * FROM combined WHERE oid = 3 ORDER BY valid_from;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\"><\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">VID OID VALID_FROM  VALID_TO    C1 C2  IS_GAP NEW_GROUP<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">--- --- ----------- ----------- -- --- ------ ---------<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">  8   3 01-JAN-2010 31-MAR-2010 C  B2       0         0<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">  7   3 01-APR-2010 31-MAY-2010 C  B1       0         0<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">  9   3 01-JUN-2010 31-AUG-2010 C  B3       0         0<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">  7   3 01-SEP-2010 30-SEP-2010 C  B1       0         0<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\"> 10   3 01-OCT-2010 31-DEC-2010 C  B4       0         0<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">      3 01-JAN-2011 31-JAN-2011             1         1<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\"> 12   3 01-FEB-2011 31-MAY-2011 C  B6       0         0<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\"> 13   3 01-JUN-2011 30-JUN-2011 C  B7       0         0<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\"> 13   3 01-JUL-2011 30-AUG-2011 C  B7       0         0<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\"> 14   3 31-AUG-2011 31-AUG-2011 C  B8       0         0<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\"> 14   3 01-SEP-2011 30-SEP-2011 C  B8       0         0<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">      3 01-OCT-2011 30-NOV-2011             1         1<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\"> 16   3 01-DEC-2011 31-MAY-2012 C  B9       0         0<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\"> 17   3 01-JUN-2012 31-DEC-2012 C  B10      0         0<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">      3 01-JAN-2013 31-DEC-9999             1         1<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\"><\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">15 rows selected.<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>Now we have cleansed the data and are ready for the final steps &#8220;calc_group&#8221; and &#8220;merge&#8221; which are very similar to scenario A. The relevant difference is the highlighted line 70 which filters non-gap records. Here is the complete statement and the query result:<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);--cbp-line-highlight-color:rgba(234, 191, 191, 0.2);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7\">SQL<\/span><span role=\"button\" tabindex=\"0\" data-code=\"WITH\n   o AS (\n      -- object identifier and their valid_from values\n      SELECT oid, valid_from FROM t2\n      UNION\n      SELECT oid, valid_to + 1 FROM t2 \n       WHERE valid_to != DATE '9999-12-31'\n   ),\n   v AS (\n      -- relevant version identifier per valid_from \n      -- produces column is_gap\n      SELECT o.oid,\n             MAX(vid) AS vid,\n             o.valid_from,\n             NVL2(MAX(vid), 0, 1) AS is_gap\n        FROM o\n        LEFT JOIN t2\n          ON t2.oid = o.oid\n             AND o.valid_from BETWEEN t2.valid_from AND t2.valid_to\n       GROUP BY o.oid, o.valid_from\n   ),\n   combined AS (\n      -- combines previous intermediate result v with t2\n      -- produces the valid_to and new_group columns\n      SELECT t2.vid,\n             v.oid,\n             v.valid_from,\n             LEAD(v.valid_from - 1, 1, DATE '9999-12-31') OVER (\n                PARTITION BY v.oid ORDER BY v.valid_from\n             ) AS valid_to,\n             t2.c1,\n             t2.c2,\n             v.is_gap,\n             CASE\n                WHEN LAG(t2.c1, 1, t2.c1) OVER(\n                        PARTITION BY t2.oid ORDER BY t2.valid_from\n                     ) = c1 THEN\n                   0\n                ELSE\n                   1\n             END AS new_group\n        FROM v\n        LEFT JOIN t2\n          ON t2.oid = v.oid\n             AND t2.vid = v.vid\n             AND v.valid_from BETWEEN t2.valid_from AND t2.valid_to \n   ),\n   calc_group AS (\n      -- produces column group_no, records with the same group_no\n      -- are mergeable, group_no is calculated per oid \n      SELECT oid,\n             valid_from,\n             valid_to,\n             c1,\n             c2,\n             is_gap,\n             SUM(is_gap + new_group) OVER(\n                PARTITION BY oid ORDER BY oid, valid_from\n             ) AS group_no\n        FROM combined\n   ),\n   merged AS (\n      -- produces the final merged result\n      -- grouping by group_no ensures that gaps are honored\n      SELECT oid,\n             MIN(valid_from) AS valid_from,\n             MAX(valid_to) AS valid_to,\n             c1\n        FROM calc_group\n       WHERE is_gap = 0\n       GROUP BY OID, c1, group_no\n       ORDER BY OID, valid_from\n   )\n-- main \nSELECT * FROM merged;\" style=\"color:#D4D4D4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dark-plus\" style=\"background-color: #1E1E1E\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #569CD6\">WITH<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">   o <\/span><span style=\"color: #569CD6\">AS<\/span><span style=\"color: #D4D4D4\"> (<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">      <\/span><span style=\"color: #6A9955\">-- object identifier and their valid_from values<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">      <\/span><span style=\"color: #569CD6\">SELECT<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">oid<\/span><span style=\"color: #D4D4D4\">, valid_from <\/span><span style=\"color: #569CD6\">FROM<\/span><span style=\"color: #D4D4D4\"> t2<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">      <\/span><span style=\"color: #569CD6\">UNION<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">      <\/span><span style=\"color: #569CD6\">SELECT<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">oid<\/span><span style=\"color: #D4D4D4\">, valid_to + <\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">FROM<\/span><span style=\"color: #D4D4D4\"> t2 <\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">       <\/span><span style=\"color: #569CD6\">WHERE<\/span><span style=\"color: #D4D4D4\"> valid_to != <\/span><span style=\"color: #569CD6\">DATE<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">&#39;9999-12-31&#39;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">   ),<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">   v <\/span><span style=\"color: #569CD6\">AS<\/span><span style=\"color: #D4D4D4\"> (<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">      <\/span><span style=\"color: #6A9955\">-- relevant version identifier per valid_from <\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">      <\/span><span style=\"color: #6A9955\">-- produces column is_gap<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">      <\/span><span style=\"color: #569CD6\">SELECT<\/span><span style=\"color: #D4D4D4\"> o.oid,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">             <\/span><span style=\"color: #DCDCAA\">MAX<\/span><span style=\"color: #D4D4D4\">(vid) <\/span><span style=\"color: #569CD6\">AS<\/span><span style=\"color: #D4D4D4\"> vid,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">             o.valid_from,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">             NVL2(<\/span><span style=\"color: #DCDCAA\">MAX<\/span><span style=\"color: #D4D4D4\">(vid), <\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">) <\/span><span style=\"color: #569CD6\">AS<\/span><span style=\"color: #D4D4D4\"> is_gap<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #569CD6\">FROM<\/span><span style=\"color: #D4D4D4\"> o<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #569CD6\">LEFT JOIN<\/span><span style=\"color: #D4D4D4\"> t2<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">          <\/span><span style=\"color: #569CD6\">ON<\/span><span style=\"color: #D4D4D4\"> t2.oid = o.oid<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">             <\/span><span style=\"color: #569CD6\">AND<\/span><span style=\"color: #D4D4D4\"> o.valid_from <\/span><span style=\"color: #569CD6\">BETWEEN<\/span><span style=\"color: #D4D4D4\"> t2.valid_from <\/span><span style=\"color: #569CD6\">AND<\/span><span style=\"color: #D4D4D4\"> t2.valid_to<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">       <\/span><span style=\"color: #569CD6\">GROUP BY<\/span><span style=\"color: #D4D4D4\"> o.oid, o.valid_from<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">   ),<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">   combined <\/span><span style=\"color: #569CD6\">AS<\/span><span style=\"color: #D4D4D4\"> (<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">      <\/span><span style=\"color: #6A9955\">-- combines previous intermediate result v with t2<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">      <\/span><span style=\"color: #6A9955\">-- produces the valid_to and new_group columns<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">      <\/span><span style=\"color: #569CD6\">SELECT<\/span><span style=\"color: #D4D4D4\"> t2.vid,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">             v.oid,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">             v.valid_from,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">             <\/span><span style=\"color: #DCDCAA\">LEAD<\/span><span style=\"color: #D4D4D4\">(v.valid_from - <\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #569CD6\">DATE<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">&#39;9999-12-31&#39;<\/span><span style=\"color: #D4D4D4\">) <\/span><span style=\"color: #569CD6\">OVER<\/span><span style=\"color: #D4D4D4\"> (<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">                <\/span><span style=\"color: #569CD6\">PARTITION<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">BY<\/span><span style=\"color: #D4D4D4\"> v.oid <\/span><span style=\"color: #569CD6\">ORDER BY<\/span><span style=\"color: #D4D4D4\"> v.valid_from<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">             ) <\/span><span style=\"color: #569CD6\">AS<\/span><span style=\"color: #D4D4D4\"> valid_to,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">             t2.c1,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">             t2.c2,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">             v.is_gap,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">             <\/span><span style=\"color: #569CD6\">CASE<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">                <\/span><span style=\"color: #569CD6\">WHEN<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #DCDCAA\">LAG<\/span><span style=\"color: #D4D4D4\">(t2.c1, <\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">, t2.c1) <\/span><span style=\"color: #569CD6\">OVER<\/span><span style=\"color: #D4D4D4\">(<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">                        <\/span><span style=\"color: #569CD6\">PARTITION<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">BY<\/span><span style=\"color: #D4D4D4\"> t2.oid <\/span><span style=\"color: #569CD6\">ORDER BY<\/span><span style=\"color: #D4D4D4\"> t2.valid_from<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">                     ) = c1 <\/span><span style=\"color: #569CD6\">THEN<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">                   <\/span><span style=\"color: #B5CEA8\">0<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">                <\/span><span style=\"color: #569CD6\">ELSE<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">                   <\/span><span style=\"color: #B5CEA8\">1<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">             <\/span><span style=\"color: #569CD6\">END<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">AS<\/span><span style=\"color: #D4D4D4\"> new_group<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #569CD6\">FROM<\/span><span style=\"color: #D4D4D4\"> v<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #569CD6\">LEFT JOIN<\/span><span style=\"color: #D4D4D4\"> t2<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">          <\/span><span style=\"color: #569CD6\">ON<\/span><span style=\"color: #D4D4D4\"> t2.oid = v.oid<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">             <\/span><span style=\"color: #569CD6\">AND<\/span><span style=\"color: #D4D4D4\"> t2.vid = v.vid<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">             <\/span><span style=\"color: #569CD6\">AND<\/span><span style=\"color: #D4D4D4\"> v.valid_from <\/span><span style=\"color: #569CD6\">BETWEEN<\/span><span style=\"color: #D4D4D4\"> t2.valid_from <\/span><span style=\"color: #569CD6\">AND<\/span><span style=\"color: #D4D4D4\"> t2.valid_to <\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">   ),<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">   calc_group <\/span><span style=\"color: #569CD6\">AS<\/span><span style=\"color: #D4D4D4\"> (<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">      <\/span><span style=\"color: #6A9955\">-- produces column group_no, records with the same group_no<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">      <\/span><span style=\"color: #6A9955\">-- are mergeable, group_no is calculated per oid <\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">      <\/span><span style=\"color: #569CD6\">SELECT<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">oid<\/span><span style=\"color: #D4D4D4\">,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">             valid_from,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">             valid_to,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">             c1,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">             c2,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">             is_gap,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">             <\/span><span style=\"color: #DCDCAA\">SUM<\/span><span style=\"color: #D4D4D4\">(is_gap + new_group) <\/span><span style=\"color: #569CD6\">OVER<\/span><span style=\"color: #D4D4D4\">(<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">                <\/span><span style=\"color: #569CD6\">PARTITION<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">BY<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">oid<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">ORDER BY<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">oid<\/span><span style=\"color: #D4D4D4\">, valid_from<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">             ) <\/span><span style=\"color: #569CD6\">AS<\/span><span style=\"color: #D4D4D4\"> group_no<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #569CD6\">FROM<\/span><span style=\"color: #D4D4D4\"> combined<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">   ),<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">   merged <\/span><span style=\"color: #569CD6\">AS<\/span><span style=\"color: #D4D4D4\"> (<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">      <\/span><span style=\"color: #6A9955\">-- produces the final merged result<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">      <\/span><span style=\"color: #6A9955\">-- grouping by group_no ensures that gaps are honored<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">      <\/span><span style=\"color: #569CD6\">SELECT<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">oid<\/span><span style=\"color: #D4D4D4\">,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">             <\/span><span style=\"color: #DCDCAA\">MIN<\/span><span style=\"color: #D4D4D4\">(valid_from) <\/span><span style=\"color: #569CD6\">AS<\/span><span style=\"color: #D4D4D4\"> valid_from,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">             <\/span><span style=\"color: #DCDCAA\">MAX<\/span><span style=\"color: #D4D4D4\">(valid_to) <\/span><span style=\"color: #569CD6\">AS<\/span><span style=\"color: #D4D4D4\"> valid_to,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">             c1<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #569CD6\">FROM<\/span><span style=\"color: #D4D4D4\"> calc_group<\/span><\/span>\n<span class=\"line cbp-line-highlight\"><span style=\"color: #D4D4D4\">       <\/span><span style=\"color: #569CD6\">WHERE<\/span><span style=\"color: #D4D4D4\"> is_gap = <\/span><span style=\"color: #B5CEA8\">0<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">       <\/span><span style=\"color: #569CD6\">GROUP BY<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">OID<\/span><span style=\"color: #D4D4D4\">, c1, group_no<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">       <\/span><span style=\"color: #569CD6\">ORDER BY<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">OID<\/span><span style=\"color: #D4D4D4\">, valid_from<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">   )<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">-- main <\/span><\/span>\n<span class=\"line\"><span style=\"color: #569CD6\">SELECT<\/span><span style=\"color: #D4D4D4\"> * <\/span><span style=\"color: #569CD6\">FROM<\/span><span style=\"color: #D4D4D4\"> merged;<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7\">Final Query Result<\/span><span role=\"button\" tabindex=\"0\" data-code=\"       OID VALID_FROM  VALID_TO    C1\n---------- ----------- ----------- ----------\n         1 01-JAN-2010 31-MAR-2011 A\n         1 01-JUN-2011 31-JAN-2012 A\n         1 01-APR-2012 31-DEC-9999 A\n         2 01-JAN-2010 31-DEC-9999 B\n         3 01-JAN-2010 31-DEC-2010 C\n         3 01-FEB-2011 30-SEP-2011 C\n         3 01-DEC-2011 31-DEC-2012 C\n         4 01-JAN-2010 30-SEP-2011 D\n         4 01-OCT-2011 30-SEP-2012\n         4 01-OCT-2012 31-DEC-9999 D\" style=\"color:#D4D4D4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dark-plus\" style=\"background-color: #1E1E1E\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #D4D4D4\">       OID VALID_FROM  VALID_TO    C1<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">---------- ----------- ----------- ----------<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">         1 01-JAN-2010 31-MAR-2011 A<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">         1 01-JUN-2011 31-JAN-2012 A<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">         1 01-APR-2012 31-DEC-9999 A<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">         2 01-JAN-2010 31-DEC-9999 B<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">         3 01-JAN-2010 31-DEC-2010 C<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">         3 01-FEB-2011 30-SEP-2011 C<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">         3 01-DEC-2011 31-DEC-2012 C<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">         4 01-JAN-2010 30-SEP-2011 D<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">         4 01-OCT-2011 30-SEP-2012<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">         4 01-OCT-2012 31-DEC-9999 D<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>If you change line 70 to &#8220;WHERE is_gap = 1&#8221; you&#8217;ll get all gap records, just a way to query non-existing intervals.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7\">All Gap Records<\/span><span role=\"button\" tabindex=\"0\" data-code=\"       OID VALID_FROM  VALID_TO    C1\n---------- ----------- ----------- ----------\n         1 01-APR-2011 31-MAY-2011\n         1 01-FEB-2012 31-MAR-2012\n         3 01-JAN-2011 31-JAN-2011\n         3 01-OCT-2011 30-NOV-2011\n         3 01-JAN-2013 31-DEC-9999\" style=\"color:#D4D4D4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dark-plus\" style=\"background-color: #1E1E1E\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #D4D4D4\">       OID VALID_FROM  VALID_TO    C1<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">---------- ----------- ----------- ----------<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">         1 01-APR-2011 31-MAY-2011<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">         1 01-FEB-2012 31-MAR-2012<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">         3 01-JAN-2011 31-JAN-2011<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">         3 01-OCT-2011 30-NOV-2011<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">         3 01-JAN-2013 31-DEC-9999<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<h3 class=\"wp-block-heading\">Conclusion<\/h3>\n\n\n\n<p>Merging temporal intervals is challenging, especially if the history has gaps and the data is inconsistent as in scenario B. However, the SQL engine is a powerful tool to clean up data and merge the temporal intervals efficiently in a single SQL statement.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In&nbsp;Joining Temporal Intervals I explained how to join multiple temporal tables. The provided solution merges also temporal intervals but &#8211; as pointed out in that post &#8211; may produce wrong results if the underlying driving table is not gaplessly historized. In this post, I&#8217;ll explain how to merge temporal intervals with various<span class=\"excerpt-hellip\"> [\u2026]<\/span><\/p>\n","protected":false},"author":1,"featured_media":766,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[5],"tags":[42,43],"class_list":["post-355","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oracle","tag-temporal-database","tag-valid-time"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.4 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Merging Temporal Intervals with Gaps - Philipp Salvisberg&#039;s Blog<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.salvis.com\/blog\/2012\/12\/27\/merging-temporal-intervals-with-gaps\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Merging Temporal Intervals with Gaps - Philipp Salvisberg&#039;s Blog\" \/>\n<meta property=\"og:description\" content=\"In&nbsp;Joining Temporal Intervals I explained how to join multiple temporal tables. The provided solution merges also temporal intervals but &#8211; as pointed out in that post &#8211; may produce wrong results if the underlying driving table is not gaplessly historized. In this post, I&#8217;ll explain how to merge temporal intervals with various [\u2026]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.salvis.com\/blog\/2012\/12\/27\/merging-temporal-intervals-with-gaps\/\" \/>\n<meta property=\"og:site_name\" content=\"Philipp Salvisberg&#039;s Blog\" \/>\n<meta property=\"article:published_time\" content=\"2012-12-27T15:05:24+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2023-11-08T19:02:18+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2012\/12\/MergingOverviewScenarioB1.png\" \/>\n\t<meta property=\"og:image:width\" content=\"749\" \/>\n\t<meta property=\"og:image:height\" content=\"294\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Philipp Salvisberg\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@phsalvisberg\" \/>\n<meta name=\"twitter:site\" content=\"@phsalvisberg\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Philipp Salvisberg\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"8 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/2012\\\/12\\\/27\\\/merging-temporal-intervals-with-gaps\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/2012\\\/12\\\/27\\\/merging-temporal-intervals-with-gaps\\\/\"},\"author\":{\"name\":\"Philipp Salvisberg\",\"@id\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/#\\\/schema\\\/person\\\/34352245c48678b1a5a05d4bc1339515\"},\"headline\":\"Merging Temporal Intervals with Gaps\",\"datePublished\":\"2012-12-27T15:05:24+00:00\",\"dateModified\":\"2023-11-08T19:02:18+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/2012\\\/12\\\/27\\\/merging-temporal-intervals-with-gaps\\\/\"},\"wordCount\":830,\"commentCount\":1,\"publisher\":{\"@id\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/#\\\/schema\\\/person\\\/34352245c48678b1a5a05d4bc1339515\"},\"image\":{\"@id\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/2012\\\/12\\\/27\\\/merging-temporal-intervals-with-gaps\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/wp-content\\\/uploads\\\/2012\\\/12\\\/MergingOverviewScenarioB1.png\",\"keywords\":[\"Temporal Database\",\"Valid Time\"],\"articleSection\":[\"Oracle\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/www.salvis.com\\\/blog\\\/2012\\\/12\\\/27\\\/merging-temporal-intervals-with-gaps\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/2012\\\/12\\\/27\\\/merging-temporal-intervals-with-gaps\\\/\",\"url\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/2012\\\/12\\\/27\\\/merging-temporal-intervals-with-gaps\\\/\",\"name\":\"Merging Temporal Intervals with Gaps - Philipp Salvisberg&#039;s Blog\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/2012\\\/12\\\/27\\\/merging-temporal-intervals-with-gaps\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/2012\\\/12\\\/27\\\/merging-temporal-intervals-with-gaps\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/wp-content\\\/uploads\\\/2012\\\/12\\\/MergingOverviewScenarioB1.png\",\"datePublished\":\"2012-12-27T15:05:24+00:00\",\"dateModified\":\"2023-11-08T19:02:18+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/2012\\\/12\\\/27\\\/merging-temporal-intervals-with-gaps\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.salvis.com\\\/blog\\\/2012\\\/12\\\/27\\\/merging-temporal-intervals-with-gaps\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/2012\\\/12\\\/27\\\/merging-temporal-intervals-with-gaps\\\/#primaryimage\",\"url\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/wp-content\\\/uploads\\\/2012\\\/12\\\/MergingOverviewScenarioB1.png\",\"contentUrl\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/wp-content\\\/uploads\\\/2012\\\/12\\\/MergingOverviewScenarioB1.png\",\"width\":749,\"height\":294},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/2012\\\/12\\\/27\\\/merging-temporal-intervals-with-gaps\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Merging Temporal Intervals with Gaps\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/#website\",\"url\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/\",\"name\":\"Philipp Salvisberg&#039;s Blog\",\"description\":\"Database-centric development\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/#\\\/schema\\\/person\\\/34352245c48678b1a5a05d4bc1339515\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/#\\\/schema\\\/person\\\/34352245c48678b1a5a05d4bc1339515\",\"name\":\"Philipp Salvisberg\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/wp-content\\\/uploads\\\/2010\\\/11\\\/phs_trivadis4.jpg\",\"url\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/wp-content\\\/uploads\\\/2010\\\/11\\\/phs_trivadis4.jpg\",\"contentUrl\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/wp-content\\\/uploads\\\/2010\\\/11\\\/phs_trivadis4.jpg\",\"width\":400,\"height\":400,\"caption\":\"Philipp Salvisberg\"},\"logo\":{\"@id\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/wp-content\\\/uploads\\\/2010\\\/11\\\/phs_trivadis4.jpg\"},\"sameAs\":[\"http:\\\/\\\/www.salvis.com\\\/\"]}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Merging Temporal Intervals with Gaps - Philipp Salvisberg&#039;s Blog","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.salvis.com\/blog\/2012\/12\/27\/merging-temporal-intervals-with-gaps\/","og_locale":"en_US","og_type":"article","og_title":"Merging Temporal Intervals with Gaps - Philipp Salvisberg&#039;s Blog","og_description":"In&nbsp;Joining Temporal Intervals I explained how to join multiple temporal tables. The provided solution merges also temporal intervals but &#8211; as pointed out in that post &#8211; may produce wrong results if the underlying driving table is not gaplessly historized. In this post, I&#8217;ll explain how to merge temporal intervals with various [\u2026]","og_url":"https:\/\/www.salvis.com\/blog\/2012\/12\/27\/merging-temporal-intervals-with-gaps\/","og_site_name":"Philipp Salvisberg&#039;s Blog","article_published_time":"2012-12-27T15:05:24+00:00","article_modified_time":"2023-11-08T19:02:18+00:00","og_image":[{"width":749,"height":294,"url":"https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2012\/12\/MergingOverviewScenarioB1.png","type":"image\/png"}],"author":"Philipp Salvisberg","twitter_card":"summary_large_image","twitter_creator":"@phsalvisberg","twitter_site":"@phsalvisberg","twitter_misc":{"Written by":"Philipp Salvisberg","Est. reading time":"8 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.salvis.com\/blog\/2012\/12\/27\/merging-temporal-intervals-with-gaps\/#article","isPartOf":{"@id":"https:\/\/www.salvis.com\/blog\/2012\/12\/27\/merging-temporal-intervals-with-gaps\/"},"author":{"name":"Philipp Salvisberg","@id":"https:\/\/www.salvis.com\/blog\/#\/schema\/person\/34352245c48678b1a5a05d4bc1339515"},"headline":"Merging Temporal Intervals with Gaps","datePublished":"2012-12-27T15:05:24+00:00","dateModified":"2023-11-08T19:02:18+00:00","mainEntityOfPage":{"@id":"https:\/\/www.salvis.com\/blog\/2012\/12\/27\/merging-temporal-intervals-with-gaps\/"},"wordCount":830,"commentCount":1,"publisher":{"@id":"https:\/\/www.salvis.com\/blog\/#\/schema\/person\/34352245c48678b1a5a05d4bc1339515"},"image":{"@id":"https:\/\/www.salvis.com\/blog\/2012\/12\/27\/merging-temporal-intervals-with-gaps\/#primaryimage"},"thumbnailUrl":"https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2012\/12\/MergingOverviewScenarioB1.png","keywords":["Temporal Database","Valid Time"],"articleSection":["Oracle"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.salvis.com\/blog\/2012\/12\/27\/merging-temporal-intervals-with-gaps\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.salvis.com\/blog\/2012\/12\/27\/merging-temporal-intervals-with-gaps\/","url":"https:\/\/www.salvis.com\/blog\/2012\/12\/27\/merging-temporal-intervals-with-gaps\/","name":"Merging Temporal Intervals with Gaps - Philipp Salvisberg&#039;s Blog","isPartOf":{"@id":"https:\/\/www.salvis.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.salvis.com\/blog\/2012\/12\/27\/merging-temporal-intervals-with-gaps\/#primaryimage"},"image":{"@id":"https:\/\/www.salvis.com\/blog\/2012\/12\/27\/merging-temporal-intervals-with-gaps\/#primaryimage"},"thumbnailUrl":"https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2012\/12\/MergingOverviewScenarioB1.png","datePublished":"2012-12-27T15:05:24+00:00","dateModified":"2023-11-08T19:02:18+00:00","breadcrumb":{"@id":"https:\/\/www.salvis.com\/blog\/2012\/12\/27\/merging-temporal-intervals-with-gaps\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.salvis.com\/blog\/2012\/12\/27\/merging-temporal-intervals-with-gaps\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.salvis.com\/blog\/2012\/12\/27\/merging-temporal-intervals-with-gaps\/#primaryimage","url":"https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2012\/12\/MergingOverviewScenarioB1.png","contentUrl":"https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2012\/12\/MergingOverviewScenarioB1.png","width":749,"height":294},{"@type":"BreadcrumbList","@id":"https:\/\/www.salvis.com\/blog\/2012\/12\/27\/merging-temporal-intervals-with-gaps\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.salvis.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Merging Temporal Intervals with Gaps"}]},{"@type":"WebSite","@id":"https:\/\/www.salvis.com\/blog\/#website","url":"https:\/\/www.salvis.com\/blog\/","name":"Philipp Salvisberg&#039;s Blog","description":"Database-centric development","publisher":{"@id":"https:\/\/www.salvis.com\/blog\/#\/schema\/person\/34352245c48678b1a5a05d4bc1339515"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.salvis.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":["Person","Organization"],"@id":"https:\/\/www.salvis.com\/blog\/#\/schema\/person\/34352245c48678b1a5a05d4bc1339515","name":"Philipp Salvisberg","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2010\/11\/phs_trivadis4.jpg","url":"https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2010\/11\/phs_trivadis4.jpg","contentUrl":"https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2010\/11\/phs_trivadis4.jpg","width":400,"height":400,"caption":"Philipp Salvisberg"},"logo":{"@id":"https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2010\/11\/phs_trivadis4.jpg"},"sameAs":["http:\/\/www.salvis.com\/"]}]}},"_links":{"self":[{"href":"https:\/\/www.salvis.com\/blog\/wp-json\/wp\/v2\/posts\/355","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.salvis.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.salvis.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.salvis.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.salvis.com\/blog\/wp-json\/wp\/v2\/comments?post=355"}],"version-history":[{"count":9,"href":"https:\/\/www.salvis.com\/blog\/wp-json\/wp\/v2\/posts\/355\/revisions"}],"predecessor-version":[{"id":12749,"href":"https:\/\/www.salvis.com\/blog\/wp-json\/wp\/v2\/posts\/355\/revisions\/12749"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.salvis.com\/blog\/wp-json\/wp\/v2\/media\/766"}],"wp:attachment":[{"href":"https:\/\/www.salvis.com\/blog\/wp-json\/wp\/v2\/media?parent=355"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.salvis.com\/blog\/wp-json\/wp\/v2\/categories?post=355"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.salvis.com\/blog\/wp-json\/wp\/v2\/tags?post=355"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}