На моей машине версии 2 и 3 выходят примерно равными и бьют две другие.
Редактировать: Хотя мне только что пришло в голову, что мой первоначальный тест был немного несправедливым на CASE
, поскольку упорядочение операторов в порядке возрастания номеров означает, что только 10 возможных чисел будут соответствоватьпервое условие и выход рано.Я добавил дополнительный тест ниже.Вы также можете попробовать вложить операторы CASE
для выполнения бинарного поиска.
SET NOCOUNT ON
SET STATISTICS TIME ON
PRINT 'Test 1';
WITH E00(N) AS (SELECT 1 UNION ALL SELECT 1),
E02(N) AS (SELECT 1 FROM E00 a, E00 b),
E04(N) AS (SELECT 1 FROM E02 a, E02 b),
E08(N) AS (SELECT 1 FROM E04 a, E04 b),
E16(N) AS (SELECT 1 FROM E08 a, E08 b),
E32(N) AS (SELECT 1 FROM E16 a, E16 b),
cteTally(N) AS (SELECT ROW_NUMBER() OVER (ORDER BY N) FROM E32)
SELECT MAX(FLOOR(LOG10(N))+1)
FROM cteTally
WHERE N <= 10000000;
PRINT 'Test 2';
WITH E00(N) AS (SELECT 1 UNION ALL SELECT 1),
E02(N) AS (SELECT 1 FROM E00 a, E00 b),
E04(N) AS (SELECT 1 FROM E02 a, E02 b),
E08(N) AS (SELECT 1 FROM E04 a, E04 b),
E16(N) AS (SELECT 1 FROM E08 a, E08 b),
E32(N) AS (SELECT 1 FROM E16 a, E16 b),
cteTally(N) AS (SELECT ROW_NUMBER() OVER (ORDER BY N) FROM E32)
SELECT MAX(LEN(CONVERT(VARCHAR, N)))
FROM cteTally
WHERE N <= 10000000;
PRINT 'Test 3';
WITH E00(N) AS (SELECT 1 UNION ALL SELECT 1),
E02(N) AS (SELECT 1 FROM E00 a, E00 b),
E04(N) AS (SELECT 1 FROM E02 a, E02 b),
E08(N) AS (SELECT 1 FROM E04 a, E04 b),
E16(N) AS (SELECT 1 FROM E08 a, E08 b),
E32(N) AS (SELECT 1 FROM E16 a, E16 b),
cteTally(N) AS (SELECT ROW_NUMBER() OVER (ORDER BY N) FROM E32)
SELECT MAX(LEN(CAST(N AS VARCHAR(10))))
FROM cteTally
WHERE N <= 10000000;
PRINT 'Test 4';
WITH E00(N) AS (SELECT 1 UNION ALL SELECT 1),
E02(N) AS (SELECT 1 FROM E00 a, E00 b),
E04(N) AS (SELECT 1 FROM E02 a, E02 b),
E08(N) AS (SELECT 1 FROM E04 a, E04 b),
E16(N) AS (SELECT 1 FROM E08 a, E08 b),
E32(N) AS (SELECT 1 FROM E16 a, E16 b),
cteTally(N) AS (SELECT ROW_NUMBER() OVER (ORDER BY N) FROM E32)
SELECT MAX(CASE
WHEN N < 10 THEN 1
WHEN N < 100 THEN 2
WHEN N < 1000 THEN 3
WHEN N < 10000 THEN 4
WHEN N < 100000 THEN 5
WHEN N < 1000000 THEN 6
WHEN N < 10000000 THEN 7
WHEN N < 100000000 THEN 8
END)
FROM cteTally
WHERE N <= 10000000;
PRINT 'Test 5';
WITH E00(N) AS (SELECT 1 UNION ALL SELECT 1),
E02(N) AS (SELECT 1 FROM E00 a, E00 b),
E04(N) AS (SELECT 1 FROM E02 a, E02 b),
E08(N) AS (SELECT 1 FROM E04 a, E04 b),
E16(N) AS (SELECT 1 FROM E08 a, E08 b),
E32(N) AS (SELECT 1 FROM E16 a, E16 b),
cteTally(N) AS (SELECT ROW_NUMBER() OVER (ORDER BY N) FROM E32)
SELECT MAX(CASE
WHEN N >= 100000000 THEN NULL
WHEN N >= 10000000 THEN 8
WHEN N >= 1000000 THEN 7
WHEN N >= 100000 THEN 6
WHEN N >= 10000 THEN 5
WHEN N >= 1000 THEN 4
WHEN N >= 100 THEN 3
WHEN N >= 10 THEN 2
ELSE 1
END )
FROM cteTally
WHERE N <= 10000000;
Результаты примера, запущенного на моем компьютере,
Test 1
CPU time = 9422 ms, elapsed time = 9523 ms.
Test 2
CPU time = 7021 ms, elapsed time = 7130 ms.
Test 3
CPU time = 6864 ms, elapsed time = 7006 ms.
Test 4
CPU time = 9328 ms, elapsed time = 9456 ms.
Test 5
CPU time = 6989 ms, elapsed time = 7358 ms.