2010-08-17 425 views
10

我是SQL函数的初学者。 在SQL Server中为factorial创建函数的最佳方式是什么 - 说10!SQL函数 - 阶乘

+2

它确实需要SQL吗?在我看来,那里会有很多其他更好的选择。 – 2010-08-17 16:57:16

+0

感谢您的回复 是的,它必须是SQL。我正在学习SQL Server上的函数 没有它不是作业,我正在通过解决我在网上找到的函数示例文件来做自我练习 – Jason 2010-08-17 17:16:02

回答

10

这里是一个递归解决方案:

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 
+0

我认为在这里使用'BIGINT'会是一个改进 – 2017-02-22 14:42:29

17

非递归的方式

;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 [email protected] 
0

我知道我是一个有点晚了这里,但值得注意的是,Martin发布的递归方式不适用于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 [email protected] 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 [email protected] UNION SELECT f=CASE WHEN @target=0 THEN 0 END) 
SELECT f FROM N0 
WHERE f>=0 

这是更快,因为我失去MAX()函数,就像top 1一样,导致DISTINCT排序。

1

...我的Set-based的方法:

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 @[email protected]*f 
FROM t 
WHERE n%[email protected]%2 OR f=0; 


SELECT @f AS FACTORIAL; 
3

- 迭代方法。 - 为什么迭代?它更简单快捷。 - 对于从0到20的@N,这给出了确切的结果。 - 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 

- 更改数据类型浮动,你可以得到阶乘高达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 

- 本

1

试试这个

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

这里是一个其他的方法来calculate factorial value of an integer in 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 numbers table此解决方案。 Select语句将FROM部分中每行的已声明整数变量与有序整数值相乘

0

如果您对近似值没有问题,请使用Stirling's Approximation

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!的情况。

+0

如果@Jason字面意思是用户定义函数在sql-server中,除了表变量之外,你不能在函数内定义一个表。 http://stackoverflow.com/questions/11267804/create-drop-and-insert-a-temp-table-in-a-user-defined-function – Jake 2017-01-03 20:44:56