2010-08-17 19 views
10

Sono un principiante nelle funzioni SQL. Qual è il modo migliore per creare una funzione per factorial in SQL Server- Dire 10!Funzioni SQL - fattoriale

+2

Ha davvero bisogno di essere SQL? Sembra che ci siano un sacco di altre opzioni migliori là fuori. –

+0

Grazie per la risposta Sì, deve essere SQL.Sto imparando le funzioni su SQL Server No non è un compito a casa, sto facendo pratica autonoma risolvendo una carta campione di funzioni che ho trovato online – Jason

risposta

10

Ecco una soluzione ricorsiva:

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

Penso che l'uso di 'BIGINT' qui sarebbe un miglioramento –

17

modo non ricorsivo

;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 

E un modo ricorsivo

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

So di essere un po 'in ritardo qui, ma vale la pena notare che il modo ricorsivo pubblicato da Martin non funziona per 0.

Questo sarà (mi perdoni, ho avuto problemi di distacco il codice):


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 

E per il modo, versione modo più veloce:

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 

Questo è molto più veloce perché io perde la funzione MAX() che, proprio come il primo 1, provoca un ordinamento DISTINCT.

1

... per il mio metodo di 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

- metodo iterativo. - Perché itterativo? È più semplice e veloce. - Per @N da 0 a 20 questo dà un risultato esatto. - 21 darà un overflow.

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 

- Modificare il tipo di dati a stare a galla e si può ottenere il fattoriale fino a 170. - 171 si tradurrà in un overflow. - Nota il risultato sarà accurato solo su un numero limitato di posizioni.

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 

- Ben

1

Prova questa

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

Ecco un altro metodo per 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 

È necessario utilizzare un SQL numbers table per questa soluzione. L'istruzione Select aggiorna la variabile intera dichiarata per ogni riga nella parte FROM moltiplicandola con i valori interi ordinati

0

Se si sta bene con un'approssimazione, utilizzare 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 

Si noti che sarà necessario creare un caso per 0 !, se necessario.

+0

Se @Jason significa letteralmente un utente definito funzione in sql-server, non è possibile definire una tabella all'interno di una funzione, oltre a una variabile di tabella. http://stackoverflow.com/questions/11267804/create-drop-and-insert-a-temp-table-in-a-user-defined-function – Jake