I am wondering if the following translation from a recursive code example (in Python here, but the language doesn't matter) is approximately correct in SQL:
def countdown(num):
if num > 0:
return countdown(num-1)
else:
return num
Now, this doesn't have any 'output', so to make it similar to SQL rows, I'm returning an array for each 'result':
res = []
def countdown(num):
res.append(num)
if num > 0:
return countdown(num-1)
else:
return res
res = countdown(4)
# [4, 3, 2, 1, 0]
And here is my attempt in SQL:
WITH RECURSIVE countdown AS
(
SELECT 4 AS num
UNION ALL
SELECT num-1 FROM countdown WHERE num > 0
)
SELECT num
FROM countdown;
num
-----
4
3
2
1
0
Is this a accurate translation? A few things that seem 'weird' to me with the SQL implementation:
- The 'parameter' (n=4) here needs to be hardcoded inside the CTE. Is there any other way around this so it reads more like a 'normal recursive function' ? I'm almost expecting something like
SELECT num FROM countdown(4). - The base condition starts things off, whereas the base condition in a procedural function 'ends things'. Is that a correct understanding?
- The
WHEREcondition essentially encodes the base condition (num > 0).
Is that a correct understanding here?
I don't know whether this helps but here is a (reasonable) procedural interpretation of what the recursive SQL might do:
When the above runs:
The
4is not a parameter, it is the initial set{4}that will be grown until the fixpoint (i.e. the set that, if grown, yields itself) has been obtained. And at that point we are done.This is quite different from growing an initially empty list (or set) until a stop condition has been reached, which is the point when all the desired elements are in the list (or set). This can be written using either loop or a recursive descent (tail-recursive or not) depending on taste. In Python one would rather use a loop as as the list holding the result is mutable and one can
insert()into it andappend()to it freely.P.S.
In languages that have immutable data structures (like Prolog or Lisp/Scheme) one would write recursive code like so (here, properly tail-recursive if one removes the
print()instructions - thus not growing the stack, as for a loop, if the tail call is optimized away, which Python does not do in any case):Then:
P.P.S.
The non-tail-recursive version:
And so: