【问题标题】:Reliability and ANSI-SQL compliance of using variables to emulate MS SQL Server ROW_NUMBER() functionality in MySQL?使用变量在 MySQL 中模拟 MS SQL Server ROW_NUMBER() 功能的可靠性和 ANSI-SQL 合规性?
【发布时间】:2013-06-25 06:12:03
【问题描述】:

正如本论坛其他地方所讨论的(例如here),可以使用 MySQL 中的变量来模拟 MS SQL Server 中的(按...排序...分区)功能的 row_number()。比如这样的代码:

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 -> col1 -> col2。

这些假设似乎打破了我习惯的 SQL 语法的通常抽象。此外,此查询要求程序员确保他/她为 col1 和 col2 提供的初始值不存在于 Table1 中。同样,在我看来,这是一个糟糕的设计。这给我带来了一个相关的问题,后一种形式(使用变量)是否符合 ANSI SQL(92 或 99),还是 MySQL 的一个特性?确定给定语法是否符合 ANSI SQL 的明确来源是什么?您是否愿意将第二个版本投入生产?

【问题讨论】:

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


    【解决方案1】:

    不,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 上太受限制了。例如,尝试找到在所有品牌的 RDBMS 中实现完全相同且完全匹配语言规范的单个 SQL 数据类型。我还没找到。

    【讨论】:

    • 如果我们专注于 MySQL,您对此有何看法,引自 MySQL 网站:“作为一般规则,您永远不应该为用户变量赋值并在同一语句中读取该值.您可能会得到您期望的结果,但这不能保证。涉及用户变量的表达式的评估顺序是未定义的,并且可能会根据给定语句中包含的元素而改变......“这不正是我们的样子在第二个查询中做什么,即在外部查询中分配和读取 col1 和 col2?
    • 该声明更多是对 MySQL 产品的一种补偿。如果他们以 SQL 标准允许的方式更改他们的实现,则要求您不要对他们感到不满。 :-)
    猜你喜欢
    • 1970-01-01
    • 2011-09-23
    • 2013-08-06
    • 2011-03-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多