创建一个以整列作为输入和输出的函数

Mic*_*ele 7 sql sql-server clr r

我编写了几个程序R,现在我需要在T-SQL中进行翻译以将它们传递给客户端.我是T-SQL的新手,我在翻译所有R功能方面遇到了一些困难.

一个例子是数值导数函数,对于两个输入列(值和时间),它将返回具有计算导数的另一列(具有相同长度).

我目前的理解是:

  1. 我不能使用SP,因为我需要使用这个函数内联 select语句,如: SELECT Customer_ID, Date, Amount, derivative(Amount, Date) FROM Customer_Detail

  2. 我不能使用UDF,因为它们可以作为输入参数仅采用标量.由于速度的原因,我需要矢量化函数,因为对于某些函数,如上所述,逐行运行没有意义(对于下一个和前一个需要的每个值)

  3. UDA采用整列,但正如名称所示......,他们会像sum或者avg那样聚合列.

如果以上是正确的,哪些其他技术可以让我创建我需要的功能类型?SQL类似于我所追求的内置函数的一个例子是square()(显然)采用一列并返回自己^ 2.我的目标是创建一个函数库,其行为类似于square,power等等.但在内部它将是不同的原因square,并返回每个标量通过行读取.我想知道是否有可能使用累积方法(如UDA)的User Defied能够对导入结束时的所有数据进行操作,然后返回相同长度的列?

注意:目前我正在使用SQL-Server 2005,但我们很快就会切换到2012年(或者可能在几个月内切换到2014年),所以基于任何2005+版本的SQL-Server的答案都可以.

编辑:R为R开发人员添加了标签,希望他们已经面临这样的困难.

EDIT2:添加了CLR标签:我经历CLR了Pro t-sql 2005程序员指南中定义的用户定义聚合.我上面已经说过,这种功能不适合我的需要,但值得深入研究.通过一个UDA所需的4种方法是:Init,Accumulate,MergeTerminate.我的请求需要通过相同的实例一起分析整个数据UDA.因此,包括merge将多核处理的部分结果组合在一起的方法的选项将不起作用.

Rom*_*kar 4

我想你可以考虑稍微改变一下主意。SQL 语言在处理数据集时非常有用,尤其是现代 RDBMS 实现(如 SQL Server 2012),但您必须按集合思考,而不是按行或列进行思考。虽然我仍然不知道你的确切任务,但让我们看看 - SQL Server 2012 有一组非常好的窗口函数+排名函数+分析函数+公用表表达式,因此你可以编写几乎任何内联查询。您可以使用公共表表达式链以任何您想要的方式转换数据、计算运行总计、计算窗口上的平均值或其他聚合等等。

实际上,我一直很喜欢 SQL,当我学习了一些函数式语言(ML 和 Scala)后,我的想法是我的 SQL 方法与函数式语言范例非常相似 - 只是对数据进行切片和切块,而不将任何内容保存到变量中,直到你得到你需要的结果。

只是简单的例子,这是 SO 的一个问题 -如何获得组中“中间”值的平均值?。目标是获得每组中间 3 个值的平均值:

TEST_ID TEST_VALUE  GROUP_ID
1       5           1       -+
2       10          1        +- these values for group_id = 1
3       15          1       -+
4       25          2       -+
5       35          2        +- these values for group_id = 2
6       5           2       -+
7       15          2       
8       25          3
9       45          3       -+
10      55          3        +- these values for group_id = 3
11      15          3       -+
12      5           3
13      25          3
14      45          4       +- this value for group_id = 4
Run Code Online (Sandbox Code Playgroud)

对我来说,在 R 中这不是一件容易的事,但在 SQL 中它可能是一个非常简单的查询,如下所示:

with cte as (
    select
        *,
        row_number() over(partition by group_id order by test_value) as rn,
        count(*) over(partition by group_id) as cnt
    from test
)
select
    group_id, avg(test_value)
from cte
where
    cnt <= 3 or
    (rn >= cnt / 2 - 1 and rn <= cnt / 2 + 1)
group by group_id
Run Code Online (Sandbox Code Playgroud)

您还可以轻松扩展此查询以获取中间的 5 个值。

仔细研究分析函数,尝试根据窗口函数重新考虑您的计算,也许用普通 SQL 重写 R 过程并不难。

希望能帮助到你。