{"id":16,"date":"2018-07-03T19:23:31","date_gmt":"2018-07-03T19:23:31","guid":{"rendered":"\/colin\/morethanfour\/post\/Using-recursive-Common-Table-Expressions-to-generate-lists"},"modified":"2018-07-03T19:23:31","modified_gmt":"2018-07-03T19:23:31","slug":"using-recursive-common-table-expressions-to-generate-lists","status":"publish","type":"post","link":"https:\/\/spacefold.com\/colin\/morethanfour\/2018\/07\/03\/using-recursive-common-table-expressions-to-generate-lists\/","title":{"rendered":"Using recursive Common Table Expressions to generate lists"},"content":{"rendered":"<p>Say we want create a generated list of values &#8211; sequential dates, for example &#8211; as a set of rows. We can do this using recursive common table expressions.<\/p>\n<p>Here&#8217;s an example of a common table expression to generate a set of dates:<\/p>\n<div id=\"codeSnippetWrapper\">\n<pre id=\"codeSnippet\" style=\"border-top-style: none; font-size: 8pt; overflow: visible; border-left-style: none; font-family: 'Courier New', courier, monospace; width: 100%; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; background-color: #f4f4f4\"><span style=\"color: #0000ff\">with<\/span> dates <span style=\"color: #0000ff\">as<\/span><br>(<br>   <span style=\"color: #0000ff\">select<\/span> <span style=\"color: #0000ff\">date<\/span> <span style=\"color: #006080\">'2012-01-01'<\/span> <span style=\"color: #0000ff\">as<\/span> DATE_VALUE <span style=\"color: #0000ff\">from<\/span> dual<br>   <span style=\"color: #0000ff\">union<\/span> <span style=\"color: #0000ff\">all<\/span><br>   <span style=\"color: #0000ff\">select<\/span> <span style=\"color: #0000ff\">date<\/span> <span style=\"color: #006080\">'2012-01-02'<\/span> <span style=\"color: #0000ff\">as<\/span> DATE_VALUE <span style=\"color: #0000ff\">from<\/span> dual<br>   <span style=\"color: #0000ff\">union<\/span> <span style=\"color: #0000ff\">all<\/span><br>   <span style=\"color: #0000ff\">select<\/span> <span style=\"color: #0000ff\">date<\/span> <span style=\"color: #006080\">'2012-01-03'<\/span> <span style=\"color: #0000ff\">as<\/span> DATE_VALUE <span style=\"color: #0000ff\">from<\/span> dual<br>)<br><span style=\"color: #0000ff\">select<\/span> * <span style=\"color: #0000ff\">from<\/span> dates;<\/pre>\n<p><\/div>\n<p>Using this technique, we could create a set of rows with sequential date values&#8230; but it is not very flexible. Ideally, we want a technique that expresses the intent algorithmically.<\/p>\n<p>In 11g R2 and later, we can use a reference to the outer table recursively from inside the definition! This sounds crazy but it works:<\/p>\n<div id=\"codeSnippetWrapper\">\n<pre id=\"codeSnippet\" style=\"border-top-style: none; font-size: 8pt; overflow: visible; border-left-style: none; font-family: 'Courier New', courier, monospace; width: 100%; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; background-color: #f4f4f4\"><span style=\"color: #0000ff\">with<\/span> dates <span style=\"color: #0000ff\">as<\/span><br>(<br>   <span style=\"color: #0000ff\">select<\/span> <span style=\"color: #0000ff\">date<\/span> <span style=\"color: #006080\">'2012-01-01'<\/span> <span style=\"color: #0000ff\">as<\/span> DATE_VALUE <span style=\"color: #0000ff\">from<\/span> dual<br>   <span style=\"color: #0000ff\">union<\/span> <span style=\"color: #0000ff\">all<\/span><br>   <span style=\"color: #0000ff\">select<\/span> d.DATE_VALUE + <span style=\"color: #0000ff\">interval<\/span> <span style=\"color: #006080\">'1'<\/span> <span style=\"color: #0000ff\">day<\/span> <span style=\"color: #0000ff\">as<\/span> DATE_VALUE<br>   <span style=\"color: #0000ff\">from<\/span> dates d<br>   <span style=\"color: #0000ff\">where<\/span> d.DATE_VALUE &lt; <span style=\"color: #0000ff\">date<\/span> <span style=\"color: #006080\">'2013-01-01'<\/span><br>)<br><span style=\"color: #0000ff\">select<\/span> * <span style=\"color: #0000ff\">from<\/span> dates;<br><\/pre>\n<\/div>\n<p>In this example, we are UNIONING the first row with a sub-select against itself, adding a new row that increments the date value by 1.<\/p>\n<p>The first time I tried this technique, I got the following error:<\/p>\n<p><font color=\"#c0504d\">ORA-32039: recursive WITH clause must have column alias list<\/font> <\/p>\n<p>Some research on the web gave me a page that explained what the problem was. The error message is actually very clear: we need to add a list of columns at the top of the WITH &lt;alias&gt; clause: <\/p>\n<div id=\"codeSnippetWrapper\">\n<pre id=\"codeSnippet\" style=\"border-top-style: none; font-size: 8pt; overflow: visible; border-left-style: none; font-family: 'Courier New', courier, monospace; width: 100%; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; background-color: #f4f4f4\"><span style=\"color: #0000ff\">with<\/span> dates ( DATE_VALUE ) <span style=\"color: #0000ff\">as<\/span><br>(<br>   <span style=\"color: #0000ff\">select<\/span> <span style=\"color: #0000ff\">date<\/span> <span style=\"color: #006080\">'2012-01-01'<\/span> <span style=\"color: #0000ff\">as<\/span> DATE_VALUE <span style=\"color: #0000ff\">from<\/span> dual<br>   <span style=\"color: #0000ff\">union<\/span> <span style=\"color: #0000ff\">all<\/span><br>   <span style=\"color: #0000ff\">select<\/span> d.DATE_VALUE + <span style=\"color: #0000ff\">interval<\/span> <span style=\"color: #006080\">'1'<\/span> <span style=\"color: #0000ff\">day<\/span> <span style=\"color: #0000ff\">as<\/span> DATE_VALUE<br>   <span style=\"color: #0000ff\">from<\/span> dates d<br>   <span style=\"color: #0000ff\">where<\/span> d.DATE_VALUE &lt; <span style=\"color: #0000ff\">date<\/span> <span style=\"color: #006080\">'2013-01-01'<\/span><br>)<br><span style=\"color: #0000ff\">select<\/span> * <span style=\"color: #0000ff\">from<\/span> dates;<br><\/pre>\n<p><\/div>\n<div>And now, it just works:<\/div>\n<\/p>\n<div id=\"codeSnippetWrapper\">\n<pre id=\"codeSnippet\" style=\"border-top-style: none; font-size: 8pt; overflow: visible; border-left-style: none; font-family: 'Courier New', courier, monospace; width: 100%; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; background-color: #f4f4f4\">SQL&gt;<br>DATE_VALUE<br>-----------<br>2012-01-01<br>2012-01-02<br>2012-01-03<br>2012-01-04<br>2012-01-05<br>2012-01-06<br>2012-01-07<br>2012-01-08<br>2012-01-09<br>2012-01-10<br>2012-01-11<br>:<\/pre>\n<p><\/div>\n<p><strong>Aside<\/strong>: Here&#8217;s how to do the same query in PostgreSQL:<\/p>\n<div id=\"codeSnippetWrapper\">\n<pre id=\"codeSnippet\" style=\"border-top-style: none; font-size: 8pt; overflow: visible; border-left-style: none; font-family: 'Courier New', courier, monospace; width: 100%; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; background-color: #f4f4f4\"><span style=\"color: #0000ff\">with<\/span> <span style=\"color: #0000ff\">recursive<\/span> dates ( DATE_VALUE ) <span style=\"color: #0000ff\">as<\/span><br>(<br>   <span style=\"color: #0000ff\">select<\/span> <span style=\"color: #0000ff\">date<\/span> <span style=\"color: #006080\">'2012-01-01'<\/span> <span style=\"color: #0000ff\">as<\/span> DATE_VALUE <br>   <span style=\"color: #0000ff\">union<\/span> <span style=\"color: #0000ff\">all<\/span><br>   <span style=\"color: #0000ff\">select<\/span> <span style=\"color: #0000ff\">cast<\/span>(d.DATE_VALUE + <span style=\"color: #0000ff\">interval<\/span> <span style=\"color: #006080\">'1'<\/span> <span style=\"color: #0000ff\">day<\/span> <span style=\"color: #0000ff\">as<\/span> <span style=\"color: #0000ff\">date<\/span>) <span style=\"color: #0000ff\">as<\/span> DATE_VALUE<br>   <span style=\"color: #0000ff\">from<\/span> dates d<br>   <span style=\"color: #0000ff\">where<\/span> d.DATE_VALUE &lt; <span style=\"color: #0000ff\">date<\/span> <span style=\"color: #006080\">'2013-01-01'<\/span><br>)<br><span style=\"color: #0000ff\">select<\/span> * <span style=\"color: #0000ff\">from<\/span> dates;   <\/pre>\n<p><\/div>\n<p>The nice thing about this technique is that we can control the end date, and the increment size, by variables: <\/p>\n<div id=\"codeSnippetWrapper\">\n<pre id=\"codeSnippet\" style=\"border-top-style: none; font-size: 8pt; overflow: visible; border-left-style: none; font-family: 'Courier New', courier, monospace; width: 100%; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; background-color: #f4f4f4\">define _increment = <span style=\"color: #006080\">'5'<\/span>;<br>define _start     = <span style=\"color: #0000ff\">date<\/span> <span style=\"color: #006080\">'2012-01-01'<\/span>;<br>define _end       = <span style=\"color: #0000ff\">date<\/span> <span style=\"color: #006080\">'2012-02-01'<\/span>;<br> <br><span style=\"color: #0000ff\">with<\/span> dates ( DATE_VALUE ) <span style=\"color: #0000ff\">as<\/span><br>(<br>   <span style=\"color: #0000ff\">select<\/span> &amp;_start <span style=\"color: #0000ff\">as<\/span> DATE_VALUE <span style=\"color: #0000ff\">from<\/span> dual<br>   <span style=\"color: #0000ff\">union<\/span> <span style=\"color: #0000ff\">all<\/span><br>   <span style=\"color: #0000ff\">select<\/span> d.DATE_VALUE + <span style=\"color: #0000ff\">interval<\/span> <span style=\"color: #006080\">'&amp;_increment'<\/span> <span style=\"color: #0000ff\">day<\/span> <span style=\"color: #0000ff\">as<\/span> DATE_VALUE<br>   <span style=\"color: #0000ff\">from<\/span> dates d<br>   <span style=\"color: #0000ff\">where<\/span> d.DATE_VALUE &lt; &amp;_end<br>)<br><span style=\"color: #0000ff\">select<\/span> * <span style=\"color: #0000ff\">from<\/span> dates;<br><\/pre>\n<p><\/div>\n<p>This gives us a list of dates 5 days apart.<\/p>\n<\/p>\n<h3>Using this technique in a PL\/SQL block<\/h3>\n<p>If you&#8217;re in a PL\/SQL block, trying to generate a list dynamically based on parameter values, the code will need to look slightly different: <\/p>\n<div id=\"codeSnippetWrapper\">\n<pre id=\"codeSnippet\" style=\"border-top-style: none; font-size: 8pt; overflow: visible; border-left-style: none; font-family: 'Courier New', courier, monospace; width: 100%; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; background-color: #f4f4f4\"><span style=\"color: #0000ff\">declare<\/span><br>   p_start_time <span style=\"color: #0000ff\">date<\/span>;<br>   p_interval_days <span style=\"color: #0000ff\">integer<\/span>;<br>   p_end_date <span style=\"color: #0000ff\">date<\/span>;<br>   <span style=\"color: #008000\">--<\/span><br><span style=\"color: #008000\">   l_interval interval day to second;<\/span><br><span style=\"color: #0000ff\">begin<\/span><br>   l_interval := numtodsinterval( p_interval_days, <span style=\"color: #006080\">'day'<\/span> );<br>   insert <span style=\"color: #0000ff\">into<\/span> My_List_Of_Dates<br>   <span style=\"color: #0000ff\">with<\/span><br>   dates ( DATE_VALUE ) <span style=\"color: #0000ff\">as<\/span><br>   (<br>      <span style=\"color: #0000ff\">select<\/span><br>         p_start_time <span style=\"color: #0000ff\">as<\/span> DATE_VALUE<br>      <span style=\"color: #0000ff\">from<\/span> dual<br>      <span style=\"color: #0000ff\">union<\/span> <span style=\"color: #0000ff\">all<\/span><br>      <span style=\"color: #0000ff\">select<\/span><br>         DATE_VALUE + l_interval <span style=\"color: #0000ff\">as<\/span> DATE_VALUE<br>      <span style=\"color: #0000ff\">from<\/span> dates d<br>      <span style=\"color: #0000ff\">where<\/span> d.END_TIME &lt; p_end_date<br>   )<br>   <span style=\"color: #0000ff\">select<\/span> DATE_VALUE <span style=\"color: #0000ff\">from<\/span> dates;<br><span style=\"color: #0000ff\">end<\/span>;<\/pre>\n<p><\/div>\n<\/p>\n<div> <\/div>\n","protected":false},"excerpt":{"rendered":"<p>Say we want create a generated list of values &#8211; sequential dates, for example &#8211; as a set of rows. We can do this using recursive common table expressions. Here&#8217;s an example of a common table expression to generate a set of dates: with dates as( select date &#8216;2012-01-01&#8217; as DATE_VALUE from dual union all [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[12,16],"tags":[],"class_list":["post-16","post","type-post","status-publish","format-standard","hentry","category-oracle","category-sql-syntax","post-preview"],"_links":{"self":[{"href":"https:\/\/spacefold.com\/colin\/morethanfour\/wp-json\/wp\/v2\/posts\/16","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/spacefold.com\/colin\/morethanfour\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/spacefold.com\/colin\/morethanfour\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/spacefold.com\/colin\/morethanfour\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/spacefold.com\/colin\/morethanfour\/wp-json\/wp\/v2\/comments?post=16"}],"version-history":[{"count":0,"href":"https:\/\/spacefold.com\/colin\/morethanfour\/wp-json\/wp\/v2\/posts\/16\/revisions"}],"wp:attachment":[{"href":"https:\/\/spacefold.com\/colin\/morethanfour\/wp-json\/wp\/v2\/media?parent=16"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/spacefold.com\/colin\/morethanfour\/wp-json\/wp\/v2\/categories?post=16"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/spacefold.com\/colin\/morethanfour\/wp-json\/wp\/v2\/tags?post=16"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}