準備体操はRuby。無駄に再帰を使う。
自然数nに対して、3つ前がFizzだったらそれ自身もFizz、 5つ前がBuzzだったらそれもBizz。
#!/usr/bin/env ruby
def isfizz(n)
  case n
  when 3
    'Fizz'
  when 1,2
    ''
  else
    isfizz(n-3)
  end
end
def isbuzz(n)
  case n
  when 5
    'Buzz'
  when 1,2,3,4
    ''
  else
    isbuzz(n-5)
  end
end
def fizzbuzz(n)
  fb = isfizz(n)+isbuzz(n)
  fb>'' ? fb : n.to_s
end
for i in 1..50
  printf("%s\n", fizzbuzz(i))
end
まずzshをインストール。
sudo apt install -y zsh
シェルなので手続き実行で戦わせてみる。
1つめのループでは自然数を出力し、出力後行頭にカーソル移動して 待機する。3か5の倍数が来たら出力した自然数を上書きする。
#!/bin/zsh
SECONDS=0.8			# 1秒に1ずつ進むシェルのグローバル変数
goal=30
i=1
next1s() {
  n=$SECONDS
  while [[ "$n" = "$SECONDS" ]]; do
    :				# 秒数が変わるまで空ループ
  done
}
while [[ $i -le $goal ]]; do
  next1s
  printf "\n%d\r" $i
  i=$((i+1))
  sleep 0.9			# 次の秒直前まで休む
done &				# 自然数を出し続けるバックグラウンドジョブ
while [[ $i -le $goal ]]; do
  next1s
  sleep 0.01
  [[ $((i%3)) -eq 0 ]] && printf 'Fizz'
  sleep 0.9
  i=$((i+1))
done &				# 3の倍数でバックグラウンド起動
while [[ $i -le $goal ]]; do
  next1s
  sleep 0.02
  [[ $((i%5)) -eq 0 ]] && printf 'Buzz'
  sleep 0.9
  i=$((i+1))
done				# 3と同じく5の倍数でフォアグラウンド起動
1から50までの自然数を以下のようにして作る。
printf "%d\n" {1..50} > 1to50.csv
以下のSQL文をsqlite3に投入する。
sqlite3 fz.sq3 < fizzbuzz.sql
-- For SQLite3
.mode csv
DROP TABLE IF EXISTS num;
CREATE TABLE num(n INTEGER);
.import 1to50.csv num
.separator ''
SELECT x.f,			-- 3で割り切れる場合の 'Fizz'
       y.b,			-- 5で割り切れる場合の 'Buzz' 
       CASE				-- 上記いずれも
       WHEN x.f IS NULL AND y.b IS NULL	-- NULLなら
       THEN x.n				-- 自然数自身をSELECT
       END
FROM   (SELECT a.n, b.f f
        FROM num a
	     LEFT JOIN
	     (SELECT n, 'Fizz' f
	      FROM num WHERE n%3 = 0) b
	     ON a.n=b.n) x
	     LEFT JOIN
	     (SELECT n,'Buzz' b
	      FROM num where n%5=0) y
	     ON x.n=y.n;
これは、「3の倍数ならFizz」を出す以下のSQL文から考えると分かりやすい。
sqlite3 fz.sq3
としてから実行してみる。
まず、1から50までの自然数で構成される「左」テーブル a を出す。
SELECT n FROM num; 1 2 3 4 5 6 7 8 9 10 : :
同様に、それが3で割り切れたら 'Fizz' を添えて出す「右」テーブル b を出す。
SELECT n, 'Fizz' AS fz FROM NUM WHERE n%3=0; 3|Fizz 6|Fizz 9|Fizz 12|Fizz 15|Fizz 18|Fizz 21|Fizz 24|Fizz 27|Fizz 30|Fizz 33|Fizz 36|Fizz 39|Fizz 42|Fizz 45|Fizz 48|Fizz
条件に当てはまらない(3で割り切れない)nの行は欠損となる。
a と b のテーブルを外部結合する。
SELECT a.n, fz
FROM num a
     LEFT JOIN
     (SELECT n, 'Fizz' AS fz FROM num WHERE n%3=0)b
     ON a.n=b.n;
1|
2|
3|Fizz
4|
5|
6|Fizz
7|
8|
9|Fizz
10|
11|
12|Fizz
    :
    :
48|Fizz
49|
50|
fzがNull値の場合のみ、nを選択するようにcoalesce関数でつなぐ。
SELECT coalesce(fz, a.n)
FROM num a
     LEFT JOIN
     (SELECT n, 'Fizz' AS fz FROM num WHERE n%3=0)b
     ON a.n=b.n;
1
2
Fizz
4
5
Fizz
7
8
Fizz
10
  :
  :
47
Fizz
49
50
以上の流れを、WITH句を利用して構造が分かりやすくなるよう 書き直したものを示しておく。
.separator ''
WITH num AS (
 SELECT 1 AS n
   UNION ALL
 SELECT n+1 FROM num WHERE n < 50
), fizz AS (
  SELECT n, 'Fizz' AS fz FROM num WHERE n%3=0
), buzz AS (
  SELECT n, 'Buzz' AS bz FROM num WHERE n%5=0
)
SELECT fz, bz,
       CASE WHEN fz IS NULL AND bz IS NULL THEN a.n END
FROM  (num a LEFT JOIN fizz b ON a.n=b.n)
       LEFT JOIN buzz c
       ON a.n=b.n AND b.n=c.n AND a.n=c.n;
sqlite3 < fz2.sql
とすると実行できる。