I am a beginner in SQL Functions. What is the best way to create a function for factorial in SQL Server- Say 10!
/* Print Factorial Sequence*/
WITH MYCTE AS(
SELECT VAL=1,NUM =1
UNION ALL
SELECT VAL=VAL*(NUM+1),NUM = (NUM +1)
FROM MYCTE
WHERE NUM < 11
)
SELECT VAL FROM MYCTE
OPTION (MAXRECURSION 0);
... for my Set-based method:
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;
I know I'm a little late here, but it's worth noting that the recursive way that Martin posted does not work for 0.
This will (forgive me, I was having issues posting the code):
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
And for the way, way faster version:
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
This is much faster because I lose the MAX() function which, just like top 1, causes a DISTINCT sort.
If you are okay with an approximation, use 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
Note that you will have to make a case for 0!, if needed.
Try this
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
You asked which is the best way to create a function for factorial in SQL Server. As always, that depends on the context. But if you truly mean it in the generic sense, where performance matters, the best way to go is without a doubt to implement it as a CLR user-defined function.
https://docs.microsoft.com/en-us/sql/relational-databases/clr-integration-database-objects-user-defined-functions/clr-user-defined-functions?view=sql-server-2017
You can of course implement the function itself in whatever language you fancy. And a long/bigint doesn't really cut it for a factorial function (a bigint can only fit up to 20!, 21! is arithmetic overflow).