SQL Server 2008 中用户定义的排名/分析函数

Posted

技术标签:

【中文标题】SQL Server 2008 中用户定义的排名/分析函数【英文标题】:User-defined ranking / analytic functions in SQL Server 2008 【发布时间】:2009-11-16 04:19:18 【问题描述】:

我正在计划将数据仓库迁移到 SQL Server 2008,并尝试想办法在 SQL Server 2008 中从 Oracle 复制 LAG、LEAD、FIRST_VALUE 和 LAST_VALUE 分析函数。它们不包含在 SQL Server 2008 中,尽管窗口分析函数的基本机制是(例如 ROW_NUMBER、RANK 和 DENSE_RANK 都存在)。

对于这些函数,可以通过创建一个子查询来实现相同的功能,该子查询使用 ROW_NUMBER 为每一行分配一个数字,然后对该查询进行自联接以查找具有附近行号的相关行(对于 LAG 和 LEAD) ,或行号 1(对于 FIRST_VALUE)。

我希望执行自联接会降低操作的效率:但我还没有 SQL Server 来测试这一点。因此,在没有实际评估性能的情况下,我想知道是否有更好的解决方法来避免自联接。

查看user-defined aggregate functions 的文档,可以想象相同的代码结构可以用于提供用户定义的分析函数。

所以我的问题是:您可以在用户定义的聚合函数之后添加一个 OVER() 子句以将其作为分析函数调用吗?

如果是这样,是否每行调用一次 Terminate() 方法?是否需要任何特别的东西来确保按照 OVER() 子句中指定的顺序将行发送到您的 UDF?

【问题讨论】:

【参考方案1】:

我会使用自联接而不是 udf。

您正在查看使用表访问的标量 UDFS,它几乎总是会导致性能不佳(它是游标)。否则,您可能会使用 APPLY,但这也是逐行的。

此外,Oracle 函数不是聚合函数。用户定义的聚合仍然需要对结果集进行相同的处理。

请记住,无论如何,Oracle 在内部仍然需要逐行处理来计算值。

因此,FIRST_VALUE 的 SQL Server 2005+ 示例(未测试)使用自联接。

注意交叉连接以解耦 FIRST_VALUE 和其余 2,因为结果集没有关系。如果您使用 UDF 或用户定义的 agg,那么很可能您必须从第一个结果集中的每行一遍又一遍地计算 FIRST_VALUE。

;WITH CTE AS
(
    SELECT
        department_id, last_name, salary,
        ROW_NUMBER() OVER (ORDER BY salary) AS ranking
    FROM employees
    WHERE department_id = 90
)
SELECT
    c1.department_id, c1.last_name, c1.salary,
    c2.last_name as Poorest
FROM
    CTE c1
    CROSS JOIN
    (SELECT last_name FROM CTE WHERE Ranking = 1) c2
ORDER BY
    c1.employee_id

【讨论】:

很公平:我希望从聚合 UDF 示例的设计中,优化器可能有更多可用选项,这些选项可能会比直接游标带来更好的性能。 Oracle 可能确实对分析函数进行了逐行处理,但它能够在一次遍历数据(排序之后)中完成此操作,这通常比等效的自连接更好。如果每行中有多个函数,您认为 UDF 是否会获得任何优势,这会导致许多自联接? 您可能可以在一个自联接中服务多个输出。在我的示例中,您可以为薪水 DESC 设置一个额外的 CTE 列,并且也可以执行 LAST_VALUE。多个 udf 会比单个 UDF 更糟糕。【参考方案2】:

在 SQL Server 中,分析是 SSAS 的一部分;你会在那里找到 FirstNonEmpty、LastNonEmpty、FirstChild、LastChild。它包含在标准版和企业版 SQL Server 中; see here。也就是说,如果您想构建多维数据集。

【讨论】:

以上是关于SQL Server 2008 中用户定义的排名/分析函数的主要内容,如果未能解决你的问题,请参考以下文章

SQL Server 2008R2 用户定义函数(表值)性能

SQL server 2008 权限

将用户定义表中的日期值传递给 SQL Server 2008 存储过程

SQL Server 2008 - 返回连接条目和“无法绑定多部分标识符”错误的用户定义函数

SQL Server 2008 - UDF 参数类型和返回类型

用户“sa”登录失败。用户未与受信任的 SQL Server 连接关联。 (Microsoft SQL Server,错误:18452)在 sql 2008 中