如何在SQL Server中执行析乘?


8

在PostgreSQL中,我经常想做一些事情,例如找到7 的阶乘

SELECT 7!;

-- PostgreSQL is so full featured
-- it even supports a prefix-factorial
SELECT !!7;

甚至Excel都有FACT

=FACT(7)

如何使用SQL Server 2017 Enterprise做到这一点?

Answers:


15

我不知道有内置函数可以执行此操作。您需要自己动手。这是我的方法:

SELECT SQL#.Math_Factorial(5); -- 120

Math_Factorial功能在免费版本的SQL# SQLCLR库(我写)。

要么

如果您不需要使用功能/ UDF形式,则执行以下操作可能会更有效:

DECLARE @BaseNumber INT = 5,
        @Result BIGINT = 1;

;WITH cte AS
(
  SELECT TOP (@BaseNumber) ROW_NUMBER() OVER (ORDER BY (SELECT 0)) AS [Num]
  FROM   sys.columns
  ORDER  BY Num
)
SELECT  @Result *= [Num]
FROM    cte;

SELECT @Result;
-- 120

上面显示的两种方法都考虑了0以“ BaseNumber” 传入的“特殊”条件,并且返回1而不是0

SELECT SQL#.Math_Factorial(0); -- 1

对于T-SQL方法,只需make即可@BaseNumber = 0返回1(无需为此再次复制并粘贴到此处)。


8

社区Wiki答案

与PostgreSQL相比,您可能会对SQL Server中的结果感到失望(PostgreSQL能够处理非常大的数字,例如30000 !,而不会损失精度)。

在SQL Server 33!是高,你可以用精确的精度,同时走170!是高,你可以都去(171!1.24E309超过的限制float)。

因此,您可以预先计算它们,并将它们存储在具有值的表中0 ... 170。如果使用压缩,则适合单个数据页。

CREATE TABLE dbo.Factorials
  (
     N               TINYINT PRIMARY KEY WITH (DATA_COMPRESSION = ROW),
     FactorialExact  NUMERIC(38, 0) NULL,
     FactorialApprox FLOAT NOT NULL
  );

WITH R(N, FactorialExact, FactorialApprox)
     AS (SELECT 0,
                CAST(1 AS NUMERIC(38, 0)),
                1E0
         UNION ALL
         SELECT R.N + 1,
                CASE WHEN R.N < 33 THEN ( R.N + 1 ) * R.FactorialExact END,
                CASE WHEN R.N < 170 THEN ( R.N + 1 ) * R.FactorialApprox END
         FROM   R
         WHERE  R.N < 170)
INSERT INTO dbo.Factorials
            (N,
             FactorialExact,
             FactorialApprox)
SELECT N,
       FactorialExact,
       FactorialApprox
FROM   R
OPTION (MAXRECURSION 170);

另外,下面将给出@N高达10精确的结果-和近似为11+(请将各种功能/常数(更准确PI()EXP()POWER())合作过DECIMAL的类型,但他们工作FLOAT只):

DECLARE @N integer = 10;

SELECT
    CONVERT
    (
        DECIMAL(38,0),
        SQRT(2 * PI() * @N) * 
        POWER(@N/EXP(1), @N) * 
        EXP(1.0/12.0/@N + 1.0/360.0/POWER(@N, 3))
    );
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.