我正在计划将数据仓库迁移到 SQL Server 2008,并试图想办法从 SQL Server 2008 中的 Oracle 复制 LAG、LEAD、FIRST_VALUE 和 LAST_VALUE 分析函数。它们不包含在 SQL Server 2008 中,尽管窗口分析函数的基 native 制是(例如 ROW_NUMBER、RANK 和 DENSE_RANK 都存在)。
对于这些功能,可以通过创建一个子查询来实现相同的功能,该子查询使用 ROW_NUMBER 为每一行分配一个数字,然后对该查询进行自连接以查找具有附近行号的相关行(对于 LAG 和 LEAD) ,或行号 1(对于 FIRST_VALUE)。
我预计进行自连接会降低操作的效率:但我还没有 SQL Server 来测试它。因此,在没有实际评估性能的情况下,我想知道是否有更好的解决方法来避免自连接。
查看 user-defined aggregate functions 的文档, 可以想象,可以使用相同的代码结构来提供用户定义的分析函数。
所以我的问题是:您可以在用户定义的聚合函数后添加一个 OVER() 子句以将其作为解析函数调用吗?
如果是,是否每行调用一次 Terminate() 方法?是否需要采取任何特殊措施来确保按照 OVER() 子句中指定的顺序将行发送到您的 UDF?
最佳答案
我会使用自连接而不是 udfs。
您正在查看使用表访问的标量 UDFS,它几乎总是提供糟糕的性能(它是一个游标)。否则,您可能会使用 APPLY,但这也是逐行进行的。
此外,Oracle 函数不是聚合函数。用户定义的聚合仍然必须对结果集执行相同的处理。
请记住,无论如何,Oracle 在内部仍会进行一些逐行处理以计算出这些值。
因此,FIRST_VALUE 的 SQL Server 2005+ 示例(未测试)使用自连接。
请注意交叉连接以分离 FIRST_VALUE 和其余 2,因为结果集没有关系。如果您使用 UDF 或用户定义的聚合,那么很可能您必须从第一个结果集中的每行一遍又一遍地计算 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
关于sql - SQL Server 2008 中用户定义的排名/分析函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1740026/