2010-08-17 128 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