正如本论坛其他地方(例如此处)所讨论的,可以使用 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 的明确来源是什么?您是否愿意将第二个版本投入生产?