2010-08-17 72 views
10

Tôi là người mới bắt đầu trong các hàm SQL. Cách tốt nhất để tạo một hàm cho giai thừa trong SQL Server- Nói 10!Các hàm SQL - giai thừa

+2

Có thực sự cần SQL không? Dường như với tôi sẽ có một tấn lựa chọn tốt hơn khác ra khỏi đó. –

+0

Cảm ơn bạn đã phản hồi Phải là SQL.Tôi đang học các hàm trên SQL Server Không phải bài tập ở nhà, tôi đang tự thực hành bằng cách giải quyết một mẫu giấy chức năng mà tôi tìm thấy trực tuyến – Jason

Trả lời

10

Dưới đây là một giải pháp đệ quy:

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

Tôi nghĩ rằng việc sử dụng 'BIGINT' ở đây sẽ là một cải tiến –

17

Một cách không đệ quy

;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 

Và một cách đệ quy

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

Tôi biết tôi là một chút trễ ở đây, nhưng cần lưu ý rằng cách đệ quy mà Martin đăng không hoạt động với 0.

này sẽ (tha thứ cho tôi, tôi đã có vấn đề đăng 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 [email protected] UNION SELECT 0) 
SELECT MAX(f) FROM N0 

Và đối với đường đi, phiên bản cách nhanh hơn:

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 

này được nhanh hơn nhiều bởi vì tôi mất hàm MAX(), giống như top 1, gây ra một kiểu DISTINCT.

1

... cho Set dựa trên phương pháp của tôi:

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

- Phương pháp lặp. - Tại sao lặp lại? Nó đơn giản và nhanh hơn. - Đối với @N từ 0 đến 20, điều này cho kết quả chính xác. - 21 sẽ bị tràn.

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 

- Thay đổi datatype nổi và bạn có thể lấy thừa lên đến 170. - 171 sẽ dẫn đến một tràn. - Lưu ý kết quả sẽ chỉ chính xác với số vị trí giới hạn.

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 

- Bến

1

Hãy thử điều này

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

Dưới đây là một phương pháp khác để 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 

Bạn cần phải sử dụng một SQL numbers table cho giải pháp này. Câu lệnh Select sẽ cập nhật biến số nguyên được khai báo cho mỗi hàng trong phần FROM bằng cách nhân nó với các giá trị số nguyên theo thứ tự

0

Nếu bạn đồng ý với một xấp xỉ, hãy sử dụng 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 

Lưu ý rằng bạn sẽ phải tạo trường hợp cho 0 !, nếu cần.

+0

Nếu @Jason theo nghĩa đen nghĩa là người dùng định nghĩa trong sql-server, bạn không thể định nghĩa một bảng bên trong một hàm, bên cạnh một biến bảng. http://stackoverflow.com/questions/11267804/create-drop-and-insert-a-temp-table-in-a-user-defined-function – Jake

Các vấn đề liên quan