【发布时间】:2015-11-18 09:02:27
【问题描述】:
我正在尝试从下面的 sql 代码创建乘法聚合函数。
declare @Floats as table (id int,value float)
insert into @Floats values (1,1)
insert into @Floats values (2,3)
insert into @Floats values (3,6)
SELECT *
FROM @Floats a
CROSS apply (SELECT CASE
WHEN MinVal = 0 THEN 0
WHEN Neg % 2 = 1 THEN -1 * Exp(ABSMult)
ELSE Exp(ABSMult)
END AS mul_value
FROM (SELECT
Sum(Log(Abs(NULLIF(Value, 0)))) AS ABSMult,
Sum(Sign(CASE
WHEN Value < 0 THEN 1
ELSE 0
END)) AS Neg,
Min(Abs(Value)) AS MinVal
FROM @Floats b
WHERE a.id >= b.id) foo) cs
结果
id value mul_value
-- ----- ---------
1 1 1
2 3 3
3 6 18
这是函数的想法。因为我们需要表格类型来将表格作为输入传递给函数,所以我们在下面创建一个
用户定义的表类型
CREATE TYPE [dbo].[UDT_TEST] AS TABLE( value float )
功能代码
CREATE FUNCTION udf_Mul(@values dbo.[UDT_TEST] readonly)
RETURNS FLOAT
AS
BEGIN
DECLARE @mul_value FLOAT
SELECT @mul_value=CASE
WHEN MinVal = 0 THEN 0
WHEN Neg % 2 = 1 THEN -1 * Exp(ABSMult)
ELSE Exp(ABSMult)
END
FROM (SELECT
--log of +ve row values
Sum(Log(Abs(NULLIF(Value, 0)))) AS ABSMult,
--count of -ve values. Even = +ve result.
Sum(Sign(CASE
WHEN Value < 0 THEN 1
ELSE 0
END)) AS Neg,
--anything * zero = zero
Min(Abs(Value)) AS MinVal
FROM @values) foo
RETURN @mul_value
END
使用这样的功能。
SELECT *
FROM @Floats a
CROSS apply (SELECT dbo.udf_mul(value) ast
FROM @Floats b
WHERE a.id >= b.id) cs
这里的问题是输入dbo.udf_mul 期望参数是[dbo].[UDT_TEST] 类型,但值列是Float 类型。
错误:
消息 206,级别 16,状态 2,第 7 行操作数类型冲突:float 是 与UDT_TEST不兼容有什么办法可以实现吗?
【问题讨论】:
-
有一种方法可以在 SQL Server 中创建自定义聚合,但它们必须在 CLR 中实现。即使在那里,我们也会遇到困难,因为您正在尝试实现一个依赖于不同列定义的顺序的聚合,而且效果不会很好。
标签: sql sql-server tsql sql-server-2012