Here's a pretty succinct way to do it. I use a recursive common-table expression to fill in a table of integers from 1 to 100.
with tbl (idx)as( select 1 union all select idx + 1 from tbl where idx < 100)select case when idx % 15 = 0 then 'fizzbuzz' when idx % 3 = 0 then 'fizz' when idx % 5 = 0 then 'buzz' else cast(idx as varchar(10)) endfrom tbl
Here's an updated version that only runs the two modulus calculations once and uses string concatenation:
with tbl (idx) as( select 1 union all select idx + 1 from tbl where idx < 100),tbl2 (idx, isFizz, isBuzz) as( select idx, iif(idx % 3 = 0, 'Fizz', ''), iif(idx % 5 = 0, 'Buzz', '') from tbl)select iif( len(isFizz) > 0 or len(isBuzz) > 0, isFizz + isBuzz, cast(idx as varchar(10)) ) as resultfrom tbl2
The first table uses a recursive CTE to generate a table with 100 rows of integers in it. The second table adds two columns that calculate the Fizz and Buzz values. The final select puts everything together using the lengths of the Fizz and Buzz columns as a guide.
Here's I think a better solution than my second solution. It uses a table filled with 3s and a table filled with 5s which together obviate the need for modulus calculations. I think that since, as the other answerer mentioned, we should be using set-based operations, this is a better solution. In the final select, I use a call to coalesce with a string concatenation to put everything together.
with t3 (idx, word) as( select 3, 'Fizz' union all select idx + 3, word from t3 where idx < 100),t5 (idx, word) as( select 5, 'Buzz' union all select idx + 5, word from t5 where idx < 100),t0 (idx) as( select 1 union all select idx + 1 from t0 where idx < 100)select coalesce(t3.word + t5.word, t3.word, t5.word, cast(t0.idx as varchar(10)))from t0left outer join t3 on t3.idx = t0.idxleft outer join t5 on t5.idx = t0.idxorder by t0.idx
The further out I abstract some of this, the uglier my code gets. I still prefer my first solution.