在MySQL中有一个很好的方法来复制SQL Server函数ROW_NUMBER()?

例如:

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

然后,例如,我可以添加一个条件,将intRow限制为1,以获得每个(col1, col2)对的col3最高的单行。


当前回答

看看这篇文章,它展示了如何在MySQL中使用分区by模拟SQL ROW_NUMBER()。我在WordPress实现中遇到了同样的场景。我需要ROW_NUMBER(),但它不在那里。

http://www.explodybits.com/2011/11/mysql-row-number/

本文中的示例使用了一个按字段划分的分区。要按额外的字段进行分区,你可以这样做:

  SELECT  @row_num := IF(@prev_value=concat_ws('',t.col1,t.col2),@row_num+1,1) AS RowNumber
         ,t.col1 
         ,t.col2
         ,t.Col3
         ,t.col4
         ,@prev_value := concat_ws('',t.col1,t.col2)
    FROM table1 t,
         (SELECT @row_num := 1) x,
         (SELECT @prev_value := '') y
   ORDER BY t.col1,t.col2,t.col3,t.col4 

使用concat_ws处理null。我使用int、date和varchar对3个字段进行了测试。希望这能有所帮助。查看这篇文章,因为它分解了这个查询并解释了它。

其他回答

对于另一个列的划分,一种方法是由@abcdn描述的。但是,它的性能很低。我建议使用这段代码,它不需要连接表本身: 考虑同一张桌子。

你可以得到这样的分区:

set @row_num := 0;
set @j:= 0;

select IF(j= @j, @row_num := @row_num + 1, @row_num := 1) as row_num,
       i, @j:= j as j
from tbl fh
order by j, i;

结果是这样的:

这样做的好处是我们不需要连接表本身

MariaDB 10.2实现了“窗口函数”,包括RANK(), ROW_NUMBER()和其他一些东西:

https://mariadb.com/kb/en/mariadb/window-functions/

根据本月在Percona Live上的一次演讲,它们得到了合理的优化。

语法与问题中的代码相同。

MySQL中没有排名功能。最接近的方法是使用变量:

SELECT t.*, 
       @rownum := @rownum + 1 AS rank
  FROM YOUR_TABLE t, 
       (SELECT @rownum := 0) r

那么在我的案例中这是如何起作用的呢?我需要两个变量,分别代表col1和col2?当col1改变时,Col2需要以某种方式重置…?

是的。如果它是Oracle,您可以使用LEAD函数在下一个值处达到峰值。值得庆幸的是,Quassnoi涵盖了在MySQL中需要实现的逻辑。

行号功能不能被模仿。你可能会得到你期望的结果,但你很可能会在某个阶段失望。 下面是mysql文档说的:

对于其他语句,例如SELECT,您可能会得到您期望的结果,但这并不保证。在下面的语句中,你可能认为MySQL会先计算@a,然后再赋值: SELECT @a, @a:=@a+1,… 但是,涉及用户变量的表达式的求值顺序是未定义的。

问候, 格奥尔基。

我也会投票给Mosty Mostacho的解决方案,对他的查询代码进行了轻微的修改:

SELECT a.i, a.j, (
    SELECT count(*) from test b where a.j >= b.j AND a.i = b.i
) AS row_number FROM test a

会得到相同的结果:

+------+------+------------+
|    i |    j | row_number |
+------+------+------------+
|    1 |   11 |          1 |
|    1 |   12 |          2 |
|    1 |   13 |          3 |
|    2 |   21 |          1 |
|    2 |   22 |          2 |
|    2 |   23 |          3 |
|    3 |   31 |          1 |
|    3 |   32 |          2 |
|    3 |   33 |          3 |
|    4 |   14 |          1 |
+------+------+------------+

对于表格:

+------+------+
|    i |    j |
+------+------+
|    1 |   11 |
|    1 |   12 |
|    1 |   13 |
|    2 |   21 |
|    2 |   22 |
|    2 |   23 |
|    3 |   31 |
|    3 |   32 |
|    3 |   33 |
|    4 |   14 |
+------+------+

唯一的区别是查询不使用JOIN和GROUP BY,而是依赖于嵌套选择。