3

我正在计划将数据仓库迁移到 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 来测试它。因此,在没有实际评估性能的情况下,我想知道是否有更好的解决方法可以避免自联接。

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

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

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

4

2 回答 2

3

我会使用自连接而不是 udfs。

您正在查看使用表访问的标量 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
于 2009-11-16T04:59:58.697 回答
1

In SQL server, analytic is part of SSAS; you will find FirstNonEmpty, LastNonEmpty, FirstChild, LastChild there. It is included with standard and enterprise versions of SQL server; see here. That is, if you wish to build cubes.

于 2009-11-16T17:13:10.013 回答