Freitag, 21. November 2014

Fibonacci numbers with Oracle WITH clause (SQL recursion)

While studying the Declaritive Programming section of Composing Programs, I stumbled accross a SQL example which calculated the fibonacci numbers using the SQL WITH clause. Since this is at work my major secret weapon to tackle complex queries I changed the example to run on Oracle SQL:

WITH compute_fib(previous, curr) AS
(
  SELECT 0, 1 FROM dual UNION ALL
  SELECT curr, previous+curr FROM compute_fib WHERE curr < 60
)
-- Oracles endless loop protection
CYCLE previous, curr SET is_cycle TO '1' DEFAULT 'Y' 

SELECT previous FROM compute_fib;

For those of you who wonder what this CYCLE expression stands for this is a good summary:

When a node is encountered for the second time, it will be included in the result set, its column value IS_CYCLE (a new column [...] with the statement above) is set to Y and the recursion stops then and there – so there will not be a second iteration starting at this node. Note however that any node where a cycle starts is included in the result set twice. [source]

This example is also introducing a nice aspect of the WITH clause I wasn't aware of so far - you can provide the column names of the subquery as arguments. See those two snippets for what I mean:

-- this is how I used to name the columns of a subquery.
-- the first SELECT of a UNION also defines the column names
WITH old_way AS
(
  SELECT 1 AS first_row, 
         2 AS second_row 
  FROM dual 
  UNION ALL
  SELECT 3, 4 FROM dual
)
SELECT * FROM old_way;


-- this is much clearer way where the subquery 
-- explicitly defines the column names
WITH new_way(first_row, second_row) AS
(
  SELECT 1, 2 FROM dual UNION ALL
  SELECT 3, 4 FROM dual
)
SELECT * FROM new_way;

Keine Kommentare:

Kommentar veröffentlichen