Mysql获取目标行号±2行

Posted

技术标签:

【中文标题】Mysql获取目标行号±2行【英文标题】:Mysql get target row number ±2 rows 【发布时间】:2020-09-09 12:33:18 【问题描述】:

我有一个My_Table,看起来像这样: PK1 | PK2 | Value | Date_Changed

还有一个基本上可以做到这一点的查询:

SELECT 
  PK1,
  PK2,
  Value,
  ROW_NUMBER() OVER ( ORDER BY Value desc, Date_Changed ASC) AS position
FROM My_Table
    where PK1 = 1;

然后我从查询结果中得到position,其中PK2 = myValue。 使用position,我返回到那个查询,并得到带有position ± 2 行的行。

我使用的是 mysql 5.7,所以我必须这样做:

SET @rownum = 0;
SET @bingo = NULL;

SELECT p.PK2 AS PK2,
       p.Value,
       p_o.Position
FROM My_Table p
         JOIN (
    SELECT PK1,
           PK2,
           @rownum := @rownum + 1 AS Position,
           CASE
               WHEN PK2 = param_PK2
                   THEN @bingo := @rownum
               ELSE 0
               END                AS bbb
    FROM My_Table
    WHERE PK1 = param_PK1
    ORDER BY value DESC, Date_Changed ASC
) p_o
              ON p.PK1 = p_o.PK1
                  AND p.PK2 = p_o.PK2
                  AND @bingo IS NOT NULL
                  AND Position < @bingo + offset
                  AND Position > @bingo - offset
ORDER BY p_o.Position;

如果经常这样做,这是一个可怕的查询。 有什么办法可以让它变轻吗? 由于它是 Mysql 5.7,我尝试在 value 列中添加一个反转值列,因为在 DESC 上跳过了索引,但它并没有太大帮助。

我也尝试通过ROW_NUMBER窗口函数来做,作为mysql 8的实验,但结果不是很好......

在这种情况下光标会有所帮助吗?

【问题讨论】:

【参考方案1】:

给定

+-----+------------+
| id  | dte        |
+-----+------------+
| 846 | 2020-04-26 |
| 847 | 2020-04-27 |
| 848 | 2020-04-28 |
| 849 | 2020-04-29 |
| 850 | 2020-04-30 |
| 851 | 2020-05-01 |
| 852 | 2020-05-02 |
| 853 | 2020-05-03 |
| 854 | 2020-05-04 |
+-----+------------+
9 rows in set (0.002 sec)

select id,dte
from dates
where dte = '2020-05-01'
union
(select id,dte
from dates
where dte < '2020-05-01'
order by dte desc limit 2
)
union all
(select id,dte
from dates
where dte > '2020-05-01'
order by dte limit 2
)
order by dte;

+-----+------------+
| id  | dte        |
+-----+------------+
| 849 | 2020-04-29 |
| 850 | 2020-04-30 |
| 851 | 2020-05-01 |
| 852 | 2020-05-02 |
| 853 | 2020-05-03 |
+-----+------------+
5 rows in set (0.004 sec)

【讨论】:

【参考方案2】:

在 MySQL 8.0 中,common-table-expression 在这里可能会派上用场:

with cte as (
    select t.*, row_number() over(order by value desc, date_changed desc) position
    from mytable t
)
select c.* 
from cte c
inner join cte c1 on c.rn between c1.rn - 2 and c1.rn + 2
where c1.pk1 = 1 and c1.pk2 = 'myvalue'

【讨论】:

以上是关于Mysql获取目标行号±2行的主要内容,如果未能解决你的问题,请参考以下文章

第四十九课文本编辑器项目持续开发

微信小程序如何获取当前行号

用JDBC操作MySQL——获取表的大小

求大神,怎么通过shell根据行号获取字符串

Ruby CSV - 获取当前行/行号

mysql获取行号