首页 > 解决方案 > 标准 SQL 中的窗口函数兼容性

问题描述

我正在探索从 SQL Server 2012 迁移数据库代码的可能性。现有代码依赖于对 SQL Server 2012 中引入的窗口函数 (WF) 的支持,因此我想了解有关如何跨不同 SQL DBMS 实现 WF 的更多信息。

即,我对标准 SQL 中 WF 支持的程度感兴趣(是否支持 OVER()、ROW_NUMBER()、RANK()、PARTITION BY、LAG()、LEAD() 等?全部/部分/没有这些标准?)

撇开语法不谈,在不同的本地 RDBMS 中如何实现 WF 是否有任何显着差异?对于基于云的数据库是否有任何考虑?

我们可以使用创建一个表

CREATE TABLE EMPLOYEE_T(Employee_Id varchar(50), Employee_name NVARCHAR(100))

INSERT EMPLOYEE_T 
  VALUES ('123-44-345','Jim Jason')
    ,('454-56-768','Robert Lewis')

以下 SQL Server (2012 v11.0.6615.2) 命令:

SELECT REPLACE(Employee_ID, '-', '') 
, COUNT(*) OVER()
, AVG(CAST(REPLACE(Employee_ID, '-', '') as numeric)) OVER()
, ROW_NUMBER() OVER(ORDER BY (SELECT NULL))
, COUNT(*) OVER (PARTITION BY Employee_ID ORDER BY (SELECT NULL) ROWS UNBOUNDED PRECEDING)
FROM EMPLOYEE_T

返回

| (no name) | (no name) | (no name) | (no name) | (no name) |<br>
|:---------:|:---------:|:---------:|:---------:|:---------:|<br>
|  12344345 |     2     |  28900556 |     1     |     1     |<br>
|  45456768 |     2     |  28900556 |     2     |     1     |<br>

以下适用于我的 Teradata Web 沙箱:

SELECT OREPLACE(Employee_ID, '-', '') 
, COUNT(*) OVER()
, AVG(CAST(OREPLACE(Employee_ID, '-', '') as int)) OVER()
, ROW_NUMBER() OVER(ORDER BY (SELECT NULL))
, COUNT(*) OVER (PARTITION BY Employee_ID ORDER BY (SELECT NULL) ROWS UNBOUNDED PRECEDING)
FROM EMPLOYEE_T

并返回

| (no name) | (no name) | (no name)   | (no name) | (no name) |<br>
|:---------:|:---------:|:-----------:|:---------:|:---------:|<br>
|  12344345 |     2     |  28900556.5 |     1     |     1     |<br>
|  45456768 |     2     |  28900556.5 |     2     |     1     |<br>

鉴于相同的结果,在我看来确实存在

除了默认值和数据类型处理的差异之外,除了 SQL Server 之外,跨 RDBMS 的 WF 功能是否有任何显着差异?在移植功能时,也许有一些实现方面值得考虑?

此外,MySQL 和 postgreSQL 是否支持这些?当代 RDBMS(例如 Azure SQL DWH 或 Snowflake)呢?

标签: sqlwindow-functions

解决方案


窗口函数是相当标准的。

SQL Server 的一个区别是RANGE窗口框架规范。这仅支持非常有限的功能。

另一个潜在的区别是ORDER BY (SELECT NULL). 我不知道是否所有数据库都支持那里的子查询。大多数可以处理一个常数。SQL Server 不允许使用常量进行排序,即使在窗口函数中也是如此。

Teradata 对窗框规范可能相当挑剔——在大多数其他数据库没有的地方需要它。我发现这相当笨拙,但其他人可能会欣赏明确的冗长。

另一个主要区别是支持哪些功能。但是,如果支持您提到的那些,几乎总是支持(SQL Server 2005 和 2008 是支持排名函数的例外,但不支持LAG()or LEAD())。


推荐阅读