如何在MySQL V5.7中模拟ROW_NUMBER()?

时间:2018-10-12 19:28:47

标签: mysql partition row-number

我知道这个问题已经被问过几次了,但是它总是在某些复杂的情况下或在理论上是不完整的。

我正在寻找一个通用的答案,例如数学公式,以便为我和将来的搜索服务。

那么,让我们看看下面的桌子...

col_a  | col_b  | prt_x  | prt_y  | ord_u  | ord_w
-------+--------+--------+--------+--------+--------
row_a1 | row_b1 | row_x1 | row_y1 | row_u1 | row_w1
row_a2 | row_b2 | row_x2 | row_y2 | row_u2 | row_w2
row_a3 | row_b3 | row_x3 | row_y3 | row_u3 | row_w3
row_a4 | row_b4 | row_x4 | row_y4 | row_u4 | row_w4

假设我们要重写下面针对MySQL V5.7的命令。

1-ROW_NUMBER,分区数为

SELECT col_a, col_b, ROW_NUMBER() OVER(PARTITION BY prt_x)
FROM tbl

解决方案:

SELECT 
    col_a, 
    col_b, 
    @row_num := IF(@part1=prt_x, @row_num + 1, 1) AS R, 
    @part1 := prt_x

FROM tbl

CROSS JOIN (SELECT @row_num := 1, @part1 := NULL) AS tbl_aux

2-ROW_NUMBER具有两个分区,

SELECT col_a, col_b, ROW_NUMBER() OVER(PARTITION BY prt_x, prt_y)
FROM tbl

解决方案:

SELECT 
    col_a, 
    col_b, 
    @row_num := IF(@part1=prt_x AND @part2=prt_y, @row_num + 1, 1) AS ROW_NUMBER, 
    @part1 := prt_x,
    @part2 := prt_y

FROM tbl

CROSS JOIN (SELECT @row_num := 1, @part1 := NULL, @part2 := NULL) AS tbl_aux

3-ROW_NUMBER(其中有一个订单)

SELECT col_a, col_b, ROW_NUMBER() OVER(PARTITION BY prt_x, prt_y, ORDER BY ord_u)
FROM tbl

解决方案:

SELECT 
    col_a, 
    col_b, 
    @row_num := IF(@part1=prt_x AND @part2=prt_y, @row_num + 1, 1) AS ROW_NUMBER, 
    @part1 := prt_x,
    @part2 := prt_y

FROM tbl

CROSS JOIN (SELECT @row_num := 1, @part1 := NULL, @part2 := NULL) AS tbl_aux ORDER BY ord_u ASC

4-ROW_NUMBER有两个订单

SELECT col_a, col_b, ROW_NUMBER() OVER(PARTITION BY prt_x, prt_y, ORDER BY ord_u, ord_v)
FROM tbl

解决方案

SELECT 
    col_a, 
    col_b, 
    @row_num := IF(@part1=prt_x AND @part2=prt_y, @row_num + 1, 1) AS ROW_NUMBER, 
    @part1 := prt_x,
    @part2 := prt_y

FROM tbl

CROSS JOIN (SELECT @row_num := 1, @part1 := NULL, @part2 := NULL) AS tbl_aux ORDER BY ord_u ASC, ord_v ASC

5-ROW_NUMBER(按RAND排序)

SELECT col_a, col_b, ROW_NUMBER() OVER(PARTITION BY prt_x, prt_y, ORDER BY ord_u, RAND())
FROM tbl

解决方案:

SELECT 
    col_a, 
    col_b, 
    @row_num := IF(@part1=prt_x AND @part2=prt_y, @row_num + 1, 1) AS ROW_NUMBER, 
    @part1 := prt_x,
    @part2 := prt_y

FROM tbl

CROSS JOIN (SELECT @row_num := 1, @part1 := NULL, @part2 := NULL) AS tbl_aux ORDER BY ord_u ASC, RAND()

6-ROW_NUMBER,按MOD排序

SELECT col_a, col_b, ROW_NUMBER() OVER(PARTITION BY prt_x, prt_y, ORDER BY ord_u, MOD(n1, n2))
FROM tbl

解决方案:

SELECT 
    col_a, 
    col_b, 
    @row_num := IF(@part1=prt_x AND @part2=prt_y, @row_num + 1, 1) AS ROW_NUMBER, 
    @part1 := prt_x,
    @part2 := prt_y

FROM tbl

CROSS JOIN (SELECT @row_num := 1, @part1 := NULL, @part2 := NULL) AS tbl_aux ORDER BY ord_u ASC, MOD(n1, n2)

0 个答案:

没有答案