SQL-функции - факториал
Я новичок в функциях SQL. Каков наилучший способ создания функции для факториала в SQL Server-скажем, 10!
8 ответов
вот рекурсивное решение:
CREATE FUNCTION dbo.Factorial ( @iNumber int )
RETURNS INT
AS
BEGIN
DECLARE @i int
IF @iNumber <= 1
SET @i = 1
ELSE
SET @i = @iNumber * dbo.Factorial( @iNumber - 1 )
RETURN (@i)
END
нерекурсивный способ
;With Nums As
(
select ROW_NUMBER() OVER (ORDER BY (SELECT 0)) AS RN
FROM sys.objects
)
SELECT POWER(10.0, SUM(LOG10(RN)))
FROM Nums
WHERE RN <= 10
и рекурсивный способ
declare @target int
set @target=10;
WITH N AS
(SELECT 1 AS i,
1 AS f
UNION ALL
SELECT i+1,
f*(i+1)
FROM N
WHERE i < @target
)
SELECT f FROM N
WHERE i=@target
-- итерационный метод. -- Почему Итеративный? Это проще и быстрее. -- Для @N от 0 до 20 это дает точный результат. -- 21 даст переполнение.
DECLARE @N Bigint = 20
DECLARE @F Bigint = 1
WHILE @N > 0 BEGIN
SET @F = @f*@n
SET @N = @N-1
END
SELECT @F AS FACTORIAL
-- измените тип данных на float, и вы можете получить факториал до 170. -- 171 приведет к переполнению. -- Примечание результат будет точным только в течение ограниченного числа позиций.
DECLARE @N FLOAT = 170
DECLARE @F FLOAT = 1
WHILE @N > 0 BEGIN
SET @F = @f*@n
SET @N = @N-1
END
SELECT @F AS FACTORIAL
-- Бен
... для моего метода на основе набора:
DECLARE @n int=11, @f bigint=1;
WITH
t(n,f) AS (SELECT TOP(@n)
ROW_NUMBER() OVER (ORDER BY (SELECT NULL))+1,
ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) *
(ROW_NUMBER() OVER (ORDER BY (SELECT NULL))+1)
FROM sys.all_columns
UNION SELECT 1, f=CASE WHEN @n=0 THEN 0 ELSE 1 END)
SELECT @f=@f*f
FROM t
WHERE n%2=@n%2 OR f=0;
SELECT @f AS FACTORIAL;
попробуй такое
WITH MYCTE AS(
SELECT VAL=1,NUM =6
UNION ALL
SELECT VAL=VAL*NUM,NUM = (NUM -1)
FROM MYCTE
WHERE NUM > 1
)
SELECT VAL FROM MYCTE
Я знаю, что немного опоздал, но стоит отметить, что рекурсивный способ, который Мартин опубликовал, не работает для 0.
это будет (простите меня, у меня были проблемы с публикацией кода):
declare @target int=3;
WITH N AS
(SELECT 1 AS i,
1 AS f
UNION ALL
SELECT i+1,
f*(i+1)
FROM N
WHERE i < @target),
N0 AS
(SELECT f FROM N WHERE i=@target UNION SELECT 0)
SELECT MAX(f) FROM N0
и для пути, путь более быстрая версия:
declare @target int=5;
WITH N AS
(SELECT 1 AS i,
1 AS f
UNION ALL
SELECT i+1,
f*(i+1)
FROM N
WHERE i < @target),
N0 AS
(SELECT f FROM N WHERE i=@target UNION SELECT f=CASE WHEN @target=0 THEN 0 END)
SELECT f FROM N0
WHERE f>=0
Это намного быстрее, потому что я теряю функцию MAX (), которая, как и top 1, вызывает отличную сортировку.
вот другой метод для вычислить факториальное значение целого числа в SQL Server
create function sqlFactorial (@int int)
returns int
begin
declare @factorial bigint = 1
select @factorial = @factorial * i from dbo.NumbersTable(1,@int,1)
return @factorial
end
вам нужно использовать таблица номеров SQL для этого решения. Инструкция Select обновляет объявленную целочисленную переменную для каждой строки в части FROM, умножая ее на упорядоченные целочисленные значения
Если вы в порядке с приближением, используйте приближение Стирлинга.
create table #temp (value int)
insert into #temp values (5),(6),(7),(8)
select
value,
sqrt(2*3.14*value)*power((value/2.718),value) --stirling's approx.
from #temp
обратите внимание, что вам придется сделать случай для 0! если понадобится.