Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>Hooray! I've found the solution that suits me and it is done without iteration</p> <pre><code>with cte1 as ( select s, t from @periods union all select max(e), null from @periods ), cte2 as ( select rn = row_number() over(order by s), s, t from cte1 ), cte3 as ( select rn = row_number() over(order by a.rn), a.s, a.t from cte2 a left join cte2 b on a.rn = b.rn + 1 and a.t = b.t where b.rn is null ) select s = a.s, e = b.s, a.t from cte3 a inner join cte3 b on b.rn = a.rn + 1; </code></pre> <p>Thanks everyone for sharing your thoughts and solutions!</p> <hr> <p>Details:</p> <p>cte1 returns the chain of dates with the types <em>after</em> them:</p> <pre><code>s t ---------- ---- 2013-01-01 3 2013-01-02 1 2013-01-04 1 2013-01-05 2 2013-01-06 2 2013-01-07 2 2013-01-08 1 2013-01-09 NULL -- there is no type *after* the last date </code></pre> <p>ct2 just add row number to the above result:</p> <pre><code> rn s t ---- ---------- ---- 1 2013-01-01 3 2 2013-01-02 1 3 2013-01-04 1 4 2013-01-05 2 5 2013-01-06 2 6 2013-01-07 2 7 2013-01-08 1 8 2013-01-09 NULL </code></pre> <p>if we output all the fields from the query in cte3 without <em>where</em> condition, we get the following results: </p> <pre><code>select * from cte2 a left join cte2 b on a.rn = b.rn + 1 and a.t = b.t; rn s t rn s t ---- ---------- ---- ------ ---------- ---- 1 2013-01-01 3 NULL NULL NULL 2 2013-01-02 1 NULL NULL NULL 3 2013-01-04 1 2 2013-01-02 1 4 2013-01-05 2 NULL NULL NULL 5 2013-01-06 2 4 2013-01-05 2 6 2013-01-07 2 5 2013-01-06 2 7 2013-01-08 1 NULL NULL NULL 8 2013-01-09 NULL NULL NULL NULL </code></pre> <p>For the dates where type is repeted there are values on the right side of the results. So we can just remove all the lines where values exist on the right side.</p> <p>So cte3 returns:</p> <pre><code>rn s t ----- ---------- ---- 1 2013-01-01 3 2 2013-01-02 1 3 2013-01-05 2 4 2013-01-08 1 5 2013-01-09 NULL </code></pre> <p>Note that because of the removal some rows there are some gaps in rn sequence, so we have to renumber them again.</p> <p>From here only one thing left - to transform the dates to periods:</p> <pre><code>select s = a.s, e = b.s, a.t from cte3 a inner join cte3 b on b.rn = a.rn + 1; </code></pre> <p>and we've got the required result:</p> <pre><code>s e t ---------- ---------- ---- 2013-01-01 2013-01-02 3 2013-01-02 2013-01-05 1 2013-01-05 2013-01-08 2 2013-01-08 2013-01-09 1 </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload