Какой наиболее эффективный метод выполнения теста FIZZBUZZ в SQL Server?

28

Это может быть не совсем по теме, однако здесь медленный день.

Существует ли более эффективный способ получения списка чисел от 1 до 49 со столбцом, содержащим слова, FIZZкогда число можно равномерно разделить на 3, BUZZкогда число можно равномерно разделить на 5, и FIZZBUZZкогда число можно равномерно разделить от обоих 3 и 5?

Мои попытки (ВНИМАНИЕ, это очистит кеш процедур, поэтому НЕ ЗАПУСКАЙТЕ ПРОДУКЦИЮ):

DBCC FREEPROCCACHE
GO
/*VARIANT1*/
;WITH t AS (
    SELECT RowNum = ROW_NUMBER() OVER (ORDER BY o.object_id)
    FROM sys.objects o
)
SELECT t.RowNum
    , CASE WHEN ((t.RowNum % 3) + (t.RowNum % 5)) = 0  THEN 'FIZZBUZZ' 
    ELSE 
        CASE WHEN t.RowNum % 3 = 0 THEN 'FIZZ' 
        ELSE 
            CASE WHEN t.RowNum % 5 = 0 THEN 'BUZZ' 
            ELSE '' 
            END 
        END 
    END
FROM t
WHERE t.RowNum < 50;
GO 100

/*VARIANT2*/
DECLARE @t TABLE
(
    Num INT NOT NULL PRIMARY KEY CLUSTERED
);
INSERT INTO @t (Num)
SELECT ROW_NUMBER() OVER (ORDER BY o.object_id)
FROM sys.objects o;

SELECT t.Num
    , CASE WHEN ((t.Num % 3) + (t.Num % 5)) = 0  THEN 'FIZZBUZZ' 
    ELSE 
        CASE WHEN t.Num % 3 = 0 THEN 'FIZZ' 
        ELSE 
            CASE WHEN t.Num % 5 = 0 THEN 'BUZZ' 
            ELSE '' 
            END 
        END 
    END
FROM @t t
WHERE t.Num < 50;
GO 100

SELECT CASE WHEN dest.text LIKE '%/*VARIANT1*/%' THEN 'VARIANT1' ELSE 'VARIANT2' END
    , MAX(deqs.execution_count)
    , SUM(deqs.total_worker_time)
    , AvgWorkerTime = SUM(deqs.total_worker_time) / MAX(deqs.execution_count)
FROM sys.dm_exec_query_stats deqs
CROSS APPLY sys.dm_exec_sql_text(deqs.sql_handle) dest
WHERE (dest.text LIKE '%/*VARIANT1*/%'
    OR dest.text LIKE '%/*VARIANT2*/%')
    AND dest.text NOT LIKE '%/*NOT_ME!*/%'
GROUP BY CASE WHEN dest.text LIKE '%/*VARIANT1*/%' THEN 'VARIANT1' ELSE 'VARIANT2' END
ORDER BY CASE WHEN dest.text LIKE '%/*VARIANT1*/%' THEN 'VARIANT1' ELSE 'VARIANT2' END
/*NOT_ME!*/;

В соответствии с рекомендациями @AaronBertrand я изменил свои попытки выполнить каждый набор операторов по 100 раз каждый, а затем показать время, записанное SQL Server до конца sys.dm_exec_query_stats.

Результаты:

            Runs    total_time      average time
VARIANT1    100     42533           425
VARIANT2    100     138677          1386
Макс Вернон
источник

Ответы:

3

Ниже представлено решение T-SQL, которое записывает первый миллион чисел во временную таблицу. На моей машине это занимает около 84 мс. Ключевые узкие места ожидают защелки NESTING_TRANSACTION_FULL, и CXPACKETоба из которых я не знаю, как обращаться, кроме изменения MAXDOP. Мне нужен был план запроса, который мог бы использовать преимущества параллельных вложенных циклов и параллелизма на основе требований, что мне удалось получить:

введите описание изображения здесь

Код немного длинный. Короче говоря, я объединяю две производные таблицы из 246 строк и 271 строки, что в общей сложности составляет 66666 строк. Эти строки объединяются в производную таблицу из 15 строк, которая использует тот факт, что шаблон FIZZBUZZ повторяется для каждых 15 строк. Последние десять строк добавляются с UNION ALL.

DROP TABLE IF EXISTS #t;

SELECT res.fizzbuzz INTO #t
FROM
(
VALUES
(0),
(15),
(30),
(45),
(60),
(75),
(90),
(105),
(120),
(135),
(150),
(165),
(180),
(195),
(210),
(225),
(240),
(255),
(270),
(285),
(300),
(315),
(330),
(345),
(360),
(375),
(390),
(405),
(420),
(435),
(450),
(465),
(480),
(495),
(510),
(525),
(540),
(555),
(570),
(585),
(600),
(615),
(630),
(645),
(660),
(675),
(690),
(705),
(720),
(735),
(750),
(765),
(780),
(795),
(810),
(825),
(840),
(855),
(870),
(885),
(900),
(915),
(930),
(945),
(960),
(975),
(990),
(1005),
(1020),
(1035),
(1050),
(1065),
(1080),
(1095),
(1110),
(1125),
(1140),
(1155),
(1170),
(1185),
(1200),
(1215),
(1230),
(1245),
(1260),
(1275),
(1290),
(1305),
(1320),
(1335),
(1350),
(1365),
(1380),
(1395),
(1410),
(1425),
(1440),
(1455),
(1470),
(1485),
(1500),
(1515),
(1530),
(1545),
(1560),
(1575),
(1590),
(1605),
(1620),
(1635),
(1650),
(1665),
(1680),
(1695),
(1710),
(1725),
(1740),
(1755),
(1770),
(1785),
(1800),
(1815),
(1830),
(1845),
(1860),
(1875),
(1890),
(1905),
(1920),
(1935),
(1950),
(1965),
(1980),
(1995),
(2010),
(2025),
(2040),
(2055),
(2070),
(2085),
(2100),
(2115),
(2130),
(2145),
(2160),
(2175),
(2190),
(2205),
(2220),
(2235),
(2250),
(2265),
(2280),
(2295),
(2310),
(2325),
(2340),
(2355),
(2370),
(2385),
(2400),
(2415),
(2430),
(2445),
(2460),
(2475),
(2490),
(2505),
(2520),
(2535),
(2550),
(2565),
(2580),
(2595),
(2610),
(2625),
(2640),
(2655),
(2670),
(2685),
(2700),
(2715),
(2730),
(2745),
(2760),
(2775),
(2790),
(2805),
(2820),
(2835),
(2850),
(2865),
(2880),
(2895),
(2910),
(2925),
(2940),
(2955),
(2970),
(2985),
(3000),
(3015),
(3030),
(3045),
(3060),
(3075),
(3090),
(3105),
(3120),
(3135),
(3150),
(3165),
(3180),
(3195),
(3210),
(3225),
(3240),
(3255),
(3270),
(3285),
(3300),
(3315),
(3330),
(3345),
(3360),
(3375),
(3390),
(3405),
(3420),
(3435),
(3450),
(3465),
(3480),
(3495),
(3510),
(3525),
(3540),
(3555),
(3570),
(3585),
(3600),
(3615),
(3630),
(3645),
(3660),
(3675)
) v246 (n)
CROSS JOIN 
(
VALUES
(0),
(15),
(30),
(45),
(60),
(75),
(90),
(105),
(120),
(135),
(150),
(165),
(180),
(195),
(210),
(225),
(240),
(255),
(270),
(285),
(300),
(315),
(330),
(345),
(360),
(375),
(390),
(405),
(420),
(435),
(450),
(465),
(480),
(495),
(510),
(525),
(540),
(555),
(570),
(585),
(600),
(615),
(630),
(645),
(660),
(675),
(690),
(705),
(720),
(735),
(750),
(765),
(780),
(795),
(810),
(825),
(840),
(855),
(870),
(885),
(900),
(915),
(930),
(945),
(960),
(975),
(990),
(1005),
(1020),
(1035),
(1050),
(1065),
(1080),
(1095),
(1110),
(1125),
(1140),
(1155),
(1170),
(1185),
(1200),
(1215),
(1230),
(1245),
(1260),
(1275),
(1290),
(1305),
(1320),
(1335),
(1350),
(1365),
(1380),
(1395),
(1410),
(1425),
(1440),
(1455),
(1470),
(1485),
(1500),
(1515),
(1530),
(1545),
(1560),
(1575),
(1590),
(1605),
(1620),
(1635),
(1650),
(1665),
(1680),
(1695),
(1710),
(1725),
(1740),
(1755),
(1770),
(1785),
(1800),
(1815),
(1830),
(1845),
(1860),
(1875),
(1890),
(1905),
(1920),
(1935),
(1950),
(1965),
(1980),
(1995),
(2010),
(2025),
(2040),
(2055),
(2070),
(2085),
(2100),
(2115),
(2130),
(2145),
(2160),
(2175),
(2190),
(2205),
(2220),
(2235),
(2250),
(2265),
(2280),
(2295),
(2310),
(2325),
(2340),
(2355),
(2370),
(2385),
(2400),
(2415),
(2430),
(2445),
(2460),
(2475),
(2490),
(2505),
(2520),
(2535),
(2550),
(2565),
(2580),
(2595),
(2610),
(2625),
(2640),
(2655),
(2670),
(2685),
(2700),
(2715),
(2730),
(2745),
(2760),
(2775),
(2790),
(2805),
(2820),
(2835),
(2850),
(2865),
(2880),
(2895),
(2910),
(2925),
(2940),
(2955),
(2970),
(2985),
(3000),
(3015),
(3030),
(3045),
(3060),
(3075),
(3090),
(3105),
(3120),
(3135),
(3150),
(3165),
(3180),
(3195),
(3210),
(3225),
(3240),
(3255),
(3270),
(3285),
(3300),
(3315),
(3330),
(3345),
(3360),
(3375),
(3390),
(3405),
(3420),
(3435),
(3450),
(3465),
(3480),
(3495),
(3510),
(3525),
(3540),
(3555),
(3570),
(3585),
(3600),
(3615),
(3630),
(3645),
(3660),
(3675),
(3690),
(3705),
(3720),
(3735),
(3750),
(3765),
(3780),
(3795),
(3810),
(3825),
(3840),
(3855),
(3870),
(3885),
(3900),
(3915),
(3930),
(3945),
(3960),
(3975),
(3990),
(4005),
(4020),
(4035),
(4050)
) v271 (n)
CROSS APPLY
(
VALUES
(CAST(v246.n * 271 + v271.n + 1 AS CHAR(8))),
(CAST(v246.n * 271 + v271.n + 2 AS CHAR(8))),
(CAST('FIZZ' AS CHAR(8))),
(CAST(v246.n * 271 + v271.n + 4 AS CHAR(8))),
(CAST('BUZZ' AS CHAR(8))),
(CAST('FIZZ' AS CHAR(8))),
(CAST(v246.n * 271 + v271.n + 7 AS CHAR(8))),
(CAST(v246.n * 271 + v271.n + 8 AS CHAR(8))),
(CAST('FIZZ' AS CHAR(8))),
(CAST('BUZZ' AS CHAR(8))),
(CAST(v246.n * 271 + v271.n + 11 AS CHAR(8))),
(CAST('FIZZ' AS CHAR(8))),
(CAST(v246.n * 271 + v271.n + 13 AS CHAR(8))),
(CAST(v246.n * 271 + v271.n + 14 AS CHAR(8))),
(CAST('FIZZBUZZ' AS CHAR(8)))
) res (fizzbuzz)

UNION ALL

SELECT v.fizzbuzz
FROM (
VALUES 
('999991'),
('999992'),
('FIZZ'),
('999994'),
('BUZZ'),
('FIZZ'),
('999997'),
('999998'),
('FIZZ'),
('BUZZ')
) v (fizzbuzz)

OPTION (MAXDOP 6, NO_PERFORMANCE_SPOOL);
Джо Оббиш
источник
Это немного обманывает, что решение на самом деле не выполняет никаких вычислений, но тогда это не было заявленным требованием. В этом решении используется нестандартное мышление ™, которое является отличительной чертой. Я хотел бы видеть это с двумя столбцами в выводе, чтобы вывод можно было легко подтвердить как правильный.
Макс Вернон
@MaxVernon Справедливо отметить, что, учитывая, что строки не упорядочены, нет смысла не включать число для всех строк. Не стесняйтесь редактировать это.
Джо Оббиш
15

Использование таблицы, оптимизированной для памяти SQL Server 2014, и встроенной процедуры:

-- Setup
CREATE DATABASE InMem;
GO
ALTER DATABASE InMem
ADD FILEGROUP FG1
CONTAINS MEMORY_OPTIMIZED_DATA;
GO
ALTER DATABASE InMem
ADD FILE 
(
    NAME = 'FN1', 
    -- Change to suit your system
    FILENAME = 'C:\Program Files\Microsoft SQL Server\MSSQL12.SQL2014\MSSQL\DATA\FN1.mod'
)
TO FILEGROUP FG1;
GO
USE InMem;
GO
CREATE TYPE dbo.FizzBuzzTableType AS TABLE 
(
    n integer NOT NULL INDEX i,
    FizzBuzz varchar(8) NOT NULL
) WITH (MEMORY_OPTIMIZED = ON);
GO

Родная процедура:

CREATE PROCEDURE dbo.FizzBuzz
WITH 
    NATIVE_COMPILATION, 
    SCHEMABINDING, 
    EXECUTE AS OWNER
AS
BEGIN ATOMIC 
WITH 
(
    TRANSACTION ISOLATION LEVEL = SNAPSHOT, 
    LANGUAGE = N'english'
)   
    DECLARE @n AS dbo.FizzBuzzTableType;

    DECLARE @i integer = 1;
    WHILE @i < 50
    BEGIN
        IF @i % 15 = 0
        BEGIN
            INSERT @n (n, FizzBuzz) 
            VALUES (@i, 'FizzBuzz')
        END
        ELSE 
        BEGIN
            IF @i % 3 = 0
            BEGIN
                INSERT @n (n, FizzBuzz)
                VALUES (@i, 'Fizz')
            END
            ELSE 
            BEGIN
                IF @i % 5 = 0
                BEGIN
                    INSERT @n (n, FizzBuzz) 
                    VALUES (@i, 'Buzz')
                END
                ELSE
                BEGIN
                    INSERT @n (n, FizzBuzz) 
                    VALUES (@i, CONVERT(varchar(8), @i));
                END;
            END;
        END;

        SET @i += 1;
    END;

    SELECT
        N.n, 
        N.FizzBuzz
    FROM @n AS N
    ORDER BY
        N.n;
END;

Тест:

SET NOCOUNT ON;
PRINT SYSUTCDATETIME();
GO
DECLARE @T AS dbo.FizzBuzzTableType;

INSERT @T (n, FizzBuzz)
EXECUTE dbo.FizzBuzz;
GO 100

PRINT SYSUTCDATETIME();

Типичные результаты:

-- 95ms for 100 iterations, < 1ms each
2014-12-31 10:07:13.7993355
Beginning execution loop
Batch execution completed 100 times.
2014-12-31 10:07:13.8943409

Это записывает вывод процедуры в переменную таблицы в памяти, потому что в противном случае мы просто тестируем скорость отображения результатов в SSMS.

Миллион строк

Приведенная выше нативная процедура занимает около 12 секунд для запуска на 1 000 000 номеров. Есть все виды более быстрых способов сделать то же самое в T-SQL. Один, который я написал ранее, следует. Он достигает примерно 500 мс на моем ноутбуке на миллион строк, когда достигается запланированный параллельный план:

IF  OBJECT_ID(N'tempdb..#Result', N'U') IS NOT NULL
    DROP TABLE #Result;

IF  OBJECT_ID(N'tempdb..#Thousand', N'U') IS NOT NULL
    DROP TABLE #Thousand;

SET NOCOUNT ON;
DECLARE @start datetime2(7) = SYSUTCDATETIME();

CREATE TABLE #Thousand 
(
    n integer NOT NULL,

    CONSTRAINT PK_#Thousand
    PRIMARY KEY CLUSTERED (n)
);

-- Add 1,000 rows numbered 0-999 to #Thousand
WITH 
    L1 (n) AS
(
    SELECT  V.n
    FROM    
    (
        VALUES  (0), (1), (2), (3), (4),
                (5), (6), (7), (8), (9)
    ) AS V (n)
),
    Thousand AS
(
    SELECT  n = 
        CONVERT
        (
            integer,
            ROW_NUMBER() OVER (
            ORDER BY (SELECT NULL))
            - 1
        )
    FROM L1
    CROSS JOIN L1 AS L2
    CROSS JOIN L1 AS L3
)
INSERT #Thousand (n)
SELECT n
FROM Thousand;

-- To hold the Fizz Buzz output
CREATE TABLE #Result 
(
    n integer NOT NULL, 
    result varchar(8) NOT NULL
);

INSERT #Result
SELECT 
    Million.n, 
    Million.result
FROM
(
    -- Modulo operation to encourage few outer rows parallelism
    SELECT  n
    FROM    #Thousand
    WHERE   n % 1 = 0
) AS T1
-- Outer Apply to keep the Compute Scalar parallel
OUTER APPLY
(
    SELECT
        F2.n, 
        F2.result
    FROM #Thousand AS T2
    CROSS APPLY
    (
        -- Row numbers 1 to 1,000,000
        SELECT  (T1.n * 1000) + T2.n + 1
    ) AS F1 (n)
    CROSS APPLY
    (
        -- The Fizz Buzz bit
        SELECT
            F1.n,
            result =
                CASE 
                    WHEN F1.n % 15 = 0 THEN 'FizzBuzz'
                    WHEN F1.n % 3 = 0 THEN 'Buzz'
                    WHEN F1.n % 5 = 0 THEN 'Fizz'
                    ELSE CONVERT(varchar(8), F1.n)
                END
    ) AS F2
) AS Million
OPTION  (MAXDOP 4, QUERYTRACEON 9481);

PRINT DATEDIFF(MILLISECOND, @start, SYSUTCDATETIME());
Пол Уайт говорит, что GoFundMonica
источник
1
Вы сказали: «Наружное применение, чтобы сохранить параллель вычислений» - можете ли вы указать мне на что-нибудь об этом?
Макс Вернон
3
Нет. Так получилось, что внешнее применение иногда может помочь предотвратить вычисление скаляров, выходящих из параллельной зоны. Полностью без документов, может измениться в любой день и т. Д.
Пол Уайт говорит, что GoFundMonica
11

Этот работает на моей машине так же, как ваш первый (0 мс). Я не уверен, будет ли он масштабироваться быстрее или нет.

;WITH t AS (
    SELECT RowNum = ROW_NUMBER() OVER (ORDER BY o.object_id)
    FROM sys.objects o
)
SELECT t.RowNum
    , Cxa.Fizz + CxB.Buzz
FROM t
CROSS APPLY (SELECT CASE WHEN t.RowNum % 3 = 0 THEN 'FIZZ' ELSE '' END) CxA(Fizz)
CROSS APPLY (SELECT CASE WHEN t.RowNum % 5 = 0 THEN 'BUZZ' ELSE '' END) CxB(Buzz)
WHERE t.RowNum < 50;
JNK
источник
10

Лучшая версия, которую я придумала, работает за 30 мс на моей машине:

WITH t AS (
    SELECT 1 As RowNum
    Union ALL
    Select RowNum + 1
    From t
    Where RowNum < 49
)
SELECT t.RowNum
, SubString('FIZZ', (t.RowNum % 3)*10, 5) + SubString('BUZZ', (t.RowNum % 5)*10, 5)
FROM t;
Роберт Л Дэвис
источник
6

Согласно sqlfiddle.com это занимает 7 мс:

select coalesce(fizz + buzz, fizz, buzz, cast(n as varchar)) as FizzBuzz
  from (
    select n0 + 3 * n3 + 9 * n9 + 27 * n27 + 81 * n81 as n
        from
            (select 0 as n0  union all select 1 union all select 2 as n0)  as n0,
            (select 0 as n3  union all select 1 union all select 2 as n3)  as n3,
            (select 0 as n9  union all select 1 union all select 2 as n9)  as n9,
            (select 0 as n27 union all select 1 union all select 2 as n27) as n27,
            (select 0 as n81 union all select 1                    as n81) as n81
  ) as stupidalias1
  left outer join
    (select 3 as fizzstep, 'Fizz' as fizz) as stupidalias2 on n % fizzstep = 0
  left outer join
    (select 5 as buzzstep, 'Buzz' as buzz) as stupidalias3 on n % buzzstep = 0
  where n between 1 and 100
  order by n;

Не использует никаких таблиц, хранимых процедур или CTE.


источник
6

Я получил разумную версию встроенного хранимого процесса, работающего на 1 миллион строк за 500-800 мс. Это преобразование T-SQL Я сделал из побитового algorithim из здесь с небольшой помощью блога Адама Machanic на побитовые операции здесь .

Я (надеюсь) следую тем же правилам, что и процедура строки @ PaulWhite 500 мс / 1 миллион строк, то есть генерирую результаты, но не отображаю их / не передаю их как часть времени. Это должны быть хеш-индексы в таблицах в памяти для скоростей и размеров сегментов 4 194 304 или 8 388 608, которые мне показались приятными, хотя, очевидно, это дает большое количество пустых сегментов.

USE hekatondb
GO

--NB: SQLCMD script, Enable via: Query menu > SQLCMD Mode
:setvar bucketCount 4194304
--:setvar bucketCount 8388608

IF OBJECT_ID('dbo.usp_hekatonFizzBuzz') IS NOT NULL
DROP PROC dbo.usp_hekatonFizzBuzz 
GO
IF OBJECT_ID('dbo.FizzBuzz') IS NOT NULL
DROP TABLE dbo.FizzBuzz
GO


IF OBJECT_ID('dbo.FizzBuzz') IS NULL
CREATE TABLE dbo.FizzBuzz (
    Number      INT NOT NULL,
    Result      VARCHAR(8) NULL,

    CONSTRAINT PK_FizzBuzz PRIMARY KEY NONCLUSTERED HASH ( Number ) WITH ( BUCKET_COUNT = $(bucketCount) )

) WITH ( MEMORY_OPTIMIZED = ON, DURABILITY = SCHEMA_ONLY )
GO


CREATE PROC dbo.usp_hekatonFizzBuzz 

    @limit  INT

WITH
    NATIVE_COMPILATION, 
    SCHEMABINDING, 
    EXECUTE AS OWNER
AS
BEGIN ATOMIC
WITH
(
    TRANSACTION ISOLATION LEVEL = SNAPSHOT, 
    LANGUAGE = N'english'
)   

    DECLARE @acc INT = 810092048    -- 11 00 00 01 00 10 01 00 00 01 10 00 01 00 00
    DECLARE @i INT = 1
    DECLARE @c INT

    WHILE @i <= @limit
    BEGIN 

        SELECT
            @c = @acc & 3,
            @acc = ( @acc / 4 ) | ( @c * 268435456 )

        INSERT dbo.FizzBuzz ( Number, Result )
        SELECT @i, SUBSTRING( '       Fizz    Buzz    FizzBuzz', @c * 8, @c * 4 )

        SET @i += 1

    END

END
GO

DELETE dbo.FizzBuzz
DECLARE @startDate DATETIME2 = SYSUTCDATETIME();

EXEC dbo.usp_hekatonFizzBuzz 1000000

SELECT DATEDIFF( millisecond, @startDate, SYSUTCDATETIME() ) diff
GO 10
wBob
источник
5

Я нашел и поиграл с этим одним суб-выбором без CTE. max_elapsed_time в статистике запросов показывает 1036

 SELECT num,
        CASE    WHEN mod3 + mod5 = 0 THEN 'FizzBuzz'
                WHEN mod5 = 0 THEN 'Buzz'
                WHEN mod3 = 0 THEN 'Fizz'
                ELSE CONVERT(VARCHAR(8), num)
        END
 FROM 
 (
    SELECT  number as num,
            number % 3 AS mod3,
            number % 5 AS mod5
    FROM    master.dbo.spt_values
    WHERE   name IS NULL
            AND number BETWEEN 1 AND 101
 ) AS numbers;
Джеймс Андерсон
источник
3

Я не беру на себя ответственность за написанный код, я просто хотел посмотреть, сколько времени это займет

ОДИН МИЛЛИАРД СТРОК!

;WITH T(N) AS (SELECT N FROM (VALUES (NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL)) AS X(N))
    ,NUMS(N) AS (SELECT TOP(1000000000) ROW_NUMBER() OVER (ORDER BY (SELECT NULL))  AS N FROM T T1,T T2,T T3,T T4,T T5,T T6,T T7,T T8,T T9, T T10)
    SELECT  n, ca.fb
    INTO #fizzywizzy
    FROM    NUMS n
            CROSS APPLY ( SELECT    CASE WHEN n.N % 15 = 0 THEN 'FizzBuzz'
                                         WHEN n.N % 3 = 0 THEN 'Fizz'
                                         WHEN n.N % 5 = 0 THEN 'Buzz'
                                         ELSE CAST(n AS VARCHAR)
                                    END AS [fb]
                        ) ca

Ответ: около 10 минут.

SQL Server parse and compile time: 
   CPU time = 13 ms, elapsed time = 13 ms.

 SQL Server Execution Times:
   CPU time = 648625 ms,  elapsed time = 618025 ms.
Эрик Дарлинг
источник
-2

PostgreSQL

PostgreSQL предоставляет generate_seriesфункцию Table-Value (Set-Returning Function), которая существенно упрощает эту задачу. Я предполагаю, что вы не хотите ничего выводить, когда число ни 3, ни 5 не входит в него.

SELECT x, str
FROM generate_series(1,49) AS gs(x)
CROSS JOIN LATERAL (VALUES (CASE
  WHEN x % 15 =0 THEN 'Fizzbuzz'
  WHEN x % 3  =0 THEN 'Fizz'
  WHEN x % 5  =0 THEN 'Buzz'
END)) AS c(str)
WHERE str IS NOT NULL;
Эван Кэрролл
источник