首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Mysql获取目标行数±2行

Mysql获取目标行数±2行
EN

Stack Overflow用户
提问于 2020-05-22 23:49:57
回答 2查看 85关注 0票数 1

我有一个类似如下的My_TablePK1 | PK2 | Value | Date_Changed

和一个查询,它本质上是这样的:

代码语言:javascript
复制
SELECT 
  PK1,
  PK2,
  Value,
  ROW_NUMBER() OVER ( ORDER BY Value desc, Date_Changed ASC) AS position
FROM My_Table
    where PK1 = 1;

然后,我从查询结果where PK2 = myValue中获得position

使用该position,我返回到该查询,并获得position±2行的行。

我使用的是MySQL5.7,所以我必须这样做:

代码语言:javascript
复制
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;

这是一个可怕的查询,如果频繁执行的话。

有没有办法让它更轻一些?

由于它是MySQL5.7,我尝试在value列中添加一个反转的值列,因为在DESC上跳过了索引,但没有太大帮助。

我也尝试过通过ROW_NUMBER窗口函数来实现,作为MySQL8的一个实验,但是效果不是很好……

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

EN

回答 2

Stack Overflow用户

发布于 2020-05-23 00:01:35

在MySQL 8.0中,公共表表达式可能会派上用场:

代码语言:javascript
复制
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'
票数 0
EN

Stack Overflow用户

发布于 2020-05-23 00:05:24

给定的

代码语言:javascript
复制
+-----+------------+
| 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)
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/61958900

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档