使用变量在MySQL中模拟MS SQL Server ROW_NUMBER()功能的可靠性和ANSI-SQL合规性?

时间:2013-06-27 16:20:21

标签: mysql sql-server row-number ansi-sql

正如本论坛其他地方所讨论的那样(例如here),人们可以使用MySQL中的变量来模拟MS SQL Server中的row_number()over ...(by by order by ...)功能。例如,像这样的代码:

SELECT 
    col1, 
    col2, 
    ROW_NUMBER() OVER (PARTITION BY col1, col2 ORDER BY col3 DESC) AS rowNum
FROM Table1

可以在MySQL中实现:

SELECT 
    @rowNum := 
        CASE 
            WHEN col1<>@col1 OR col2<>@col2 THEN 1 
            ELSE @rowNum+1 
        END rowNum
    , @col1 := col1 col1
    , @col2 := col2 col2
    FROM
    (SELECT @col1 := 'xxx', @col2 := 'yyy', @rowNum := 0) a,
    (SELECT col1, col2, col3 FROM Table1 ORDER BY col1, col2, col3 DESC) b

虽然这很快(因为它避免了自我加入),但是我对将它投入生产犹豫不决,因为它对查询执行计划做出了详细的假设,这可能是也可能不是可移植的。特别是,它假定:

1)表'b'的行由外部查询

按其排序顺序处理

2)外部查询的列从左到右计算(即rowNum - &gt; col1 - &gt; col2。

这些假设似乎打破了我习惯的SQL语法的常规抽象。此外,此查询要求程序员确保表1中不存在他/她为col1和col2提供的初始值。同样,在我看来,这是糟糕的设计。这让我想到了一个相关的问题,这是后一种形式(使用变量)ANSI SQL兼容(92或99),还是MySQL的一个特性?确定给定语法是否是ANSI SQL投诉的确定来源是什么?您是否觉得足够舒适地将第二个版本投入生产?

1 个答案:

答案 0 :(得分:0)

不,MySQL解决方案不是标准SQL。 MySQL用户变量是ANSI / ISO SQL的扩展。

SQL-99 Complete, Really是一个免费的在线资源,以人类可读的方式描述SQL规范。它是一个在线版本,希望在其作者的许可下发布the book by the same name

但是,我不知道SQL:2003或更高版本的类似资源。你必须purchase the specification documents from ISO。它们并不便宜,而且阅读干燥。

恕我直言,试图将自己限制在100%可移植的SQL并且符合语言抽象的限制。例如,尝试查找单个SQL数据类型,它在所有RDBMS品牌中实现完全相同,并且与语言规范完全匹配。我还没找到。