Post

Euler Project using Postgres

This is the first post of a series about using SQL, and postgres of course, to solve Project Euler problems. This started as an exercise to master advanced features of postgres/SQL. When I realized that some solutions were quite elegant, I decided to share them here. I’ve also setup github discussions in this blog so that you can give a feedback.

Problem 2

Fibonacci Series! This is a classic problem usually solved with a loop. Ops, we don’t have loops in SQL, at least not explictly. More specifically, this loop is a while and not a for loop. The closest thing I’ve found is a recursive CTE. As explained in the docs, recursive CTEs are internally evaluated as an iteration.

This solution use the most basic features of recursive CTEs. Let’s not hurry. We have enough complexity to start with. It is easier to explain the syntax of a recursive CTE with an example:

1
2
3
4
5
6
with recursive t(n) as (
    values(1) -- initial value of t(n)
  union 
    select n+1 from t -- iteration step
)
select * from t limit 5;
n
1
2
3
4
5

The query above generates a incremental sequence starting from 1. It is an infinite sequence so if we do not put a limit the query will never end. The structure of the recursive CTE has two placeholders: the stuff before union and the stuff after union. They are respectively the initial content of the table and the iteration step by which the table grows. The rest follows as a standard CTE.

Generating a Fibonacci table

1
2
3
4
5
6
7
8
with recursive fibonacci(previous_term, term) as (
    values (1, 1)
  union
    select term                 as previous_term,
           previous_term + term as term
    from   fibonacci
)
select * from fibonacci limit 10;
previous_termterm
11
12
23
35
58
813
1321
2134
3455
5589

Final solution

This problem asks all even numbers in the series below a given threshold. Inside the recursive CTE we cut the series with a where term and we sum all even terms in the concluding select statement.

1
2
3
4
5
6
7
8
9
with recursive fibonacci(previous_term, term) as (
    values (1, 1)
  union
    select term                 as previous_term,
           previous_term + term as term
    from   fibonacci
    where  term < 4*1000*1000
)
select sum(term) from fibonacci where mod(term,2)=0

Now that I’m used to the recursive CTE syntax, this solution seems quite elegant to my eyes. Well, maybe I write too much SQL…

This post is licensed under CC BY 4.0 by the author.