SQL Queries
The following examples are not mine but this is soooo cool :)
Mandelbrot Set
Source: https://blog.jooq.org/fun-with-postgis-mandelbrot-set-game-of-life-and-more/
With the code below, use different values for "dims" to zoom in, e.g.
dims (r1, r2, i1, i2, s, it, p) as (values (
  (-0.925-0.032)::float, (-0.925+0.032)::float, 
  (0.266-0.032)::float, (0.266+0.032)::float, 
  0.00005::float, 100, 256.0::float)
)
Code
WITH RECURSIVE
  -- These are the dimensions that you can play around with
  dims (r1, r2, i1, i2, s, it, p) AS (
    VALUES (
      -- The dimensions of the real axis
      -2::float, 1::float, 
      -- The dimensions of the imaginary axis
      -1.5::float, 1.5::float, 
      -- The step size on each axis, per pixel or sprite
      0.01::float, 
      -- The maximum number of iterations
      100, 
      -- "Infinity", i.e. when to stop
      256.0::float
    )
  ),
  -- The square again, as before
  sprites (s) AS (VALUES
    (st_polygonfromtext('polygon ((0 0, 0 1, 1 1, 1 0, 0 0))'))
  ),
  -- The number plane, as ints
  n1 (r, i) AS (
    SELECT r, i 
    FROM
      dims, 
      generate_series((r1 / s)::int, (r2 / s)::int) r,
      generate_series((i1 / s)::int, (i2 / s)::int) i
  ),
  -- The number plane as scaled floats
  n2 (r, i) AS (
    SELECT r::float * s::float, i::float * s::float
    FROM dims, n1
  ),
  -- The recursive calculation of the Mandelbrot formula
  -- zn = (zn-1)^2 + c
  l (cr, ci, zr, zi, g, it, p) AS (
    SELECT r, i, 0::float, 0::float, 0, it, p FROM n2, dims
    UNION ALL
    SELECT cr, ci, zr*zr - zi*zi + cr, 2*zr*zi + ci, g + 1, it, p 
    FROM l
    -- The recursions stops when we reach the maximum
    WHERE g < it
    -- Or, when we reach "infinity"
    AND zr*zr + zi*zi < p
  ),
  -- Find the last calculated value per point in the
  -- complex number plane c (cr, ci), discard the others
  x (cr, ci, zr, zi, g) AS (
    SELECT DISTINCT ON (cr, ci) cr, ci, zr, zi, g
    FROM l
    ORDER BY cr, ci, g DESC
  )
-- Turn every calculated point into a square
SELECT
  st_union(
    st_translate(sprites.s, round(cr / dims.s), round(ci / dims.s))
  )
FROM x, sprites, dims
-- Retain only the points *not* belonging to the Mandelbrot set
-- You can also inverse the equation to retain the points that
-- belong to the set
WHERE zr*zr + zi*zi > p;
Example output:

Another mandlebrot alternative
WITH RECURSIVE  xaxis(x) AS (VALUES(-2.0) UNION ALL SELECT x+0.05 FROM xaxis WHERE x<1.2),
  yaxis(y) AS (VALUES(-1.0) UNION ALL SELECT y+0.1 FROM yaxis WHERE y<1.0),
  m(iter, cx, cy, x, y) AS (
    SELECT 0, x, y, 0.0, 0.0 FROM xaxis, yaxis
    UNION ALL
    SELECT iter+1, cx, cy, x*x-y*y + cx, 2.0*x*y + cy FROM m 
     WHERE (x*x + y*y) < 4.0 AND iter<28
  ),
  m2(iter, cx, cy) AS (
    SELECT max(iter), cx, cy FROM m GROUP BY cx, cy
  ),
  a(t) AS (
    SELECT group_concat( substr(' .+*#', 1+min(iter/7,4), 1), '') 
    FROM m2 GROUP BY cy
  )
SELECT group_concat(rtrim(t),x'0a') as Mandelbrot FROM a;
Example output:

Christmas Tree
ASCII art christmas tree using Recursion and CTEs.
Code
WITH small_tree(tree_depth,pine) AS (
  SELECT 1 tree_depth,
  rpad(' ',10,' ') || '*'
  || rpad(' ',20,' ') || '*'
  || rpad(' ',20,' ') || '*'
  pine
  FROM   dual
  UNION ALL
  SELECT small_tree.tree_depth +1 tree_depth,
  rpad(' ',10-small_tree.tree_depth,' ') || rpad('*',small_tree.tree_depth+1,'.') || lpad('*',small_tree.tree_depth,'.')
  || rpad(' ',20-small_tree.tree_depth-tree_depth,' ') || rpad('*',small_tree.tree_depth+1,'.') || lpad('*',small_tree.tree_depth,'.')
  || rpad(' ',20-small_tree.tree_depth-tree_depth,' ') || rpad('*',small_tree.tree_depth+1,'.') || lpad('*',small_tree.tree_depth,'.') pine
  FROM   small_tree
  where small_tree.tree_depth < 10
)
SELECT pine
FROM small_tree;
Result
          *                    *                    *
          *.*                  *.*                  *.*
        *...*                *...*                *...*
        *.....*              *.....*              *.....*
      *.......*            *.......*            *.......*
      *.........*          *.........*          *.........*
    *...........*        *...........*        *...........*
    *.............*      *.............*      *.............*
  *...............*    *...............*    *...............*
  *.................*  *.................*  *.................*
Man with a Hat
Draw a man with a hat using recursive queries and Common Table Expressions (CTEs).
Code
WITH RECURSIVE hat
AS (
  SELECT
    CAST(REPEAT(' ', 11) || '/V\' AS VARCHAR(100))
      AS hat_pattern,
    1 AS level
  UNION ALL
  SELECT
    CAST(
      REPEAT(' ', 10-level) || '/'
        || REPEAT('V', 2 * level + 1) || 'V\'
        AS VARCHAR(100))
      AS repeated_pattern,
    hat.level + 1
  FROM hat
  WHERE level < 6
)
SELECT hat_pattern
FROM hat
UNION ALL
SELECT
  CAST(
    REPEAT(' ', 5) || '|' || '             ' || '|'
    AS VARCHAR(100))
  AS forehead
UNION ALL
SELECT
  CAST(
    REPEAT(' ', 5) || '|' || '  O   /   O  ' || '|'
    AS VARCHAR(100))
  AS eyes
UNION ALL
SELECT
  CAST(
    REPEAT(' ', 5) || '|' || '     /_      ' || '|'
    AS VARCHAR(100))
  AS nose
UNION ALL
SELECT
  CAST(
    REPEAT(' ', 5) || '|' || '     ~~~~~   ' || '|'
    AS VARCHAR(100))
  AS mouth
UNION ALL
SELECT
  CAST(
    REPEAT(' ', 5) || '|' || '   {  |  }   ' || '|'
    AS VARCHAR(100))
  AS chin;
