MySql:查找特定记录的行号

use*_*490 3 mysql pagination

我正在使用一个通用数据面板,该面板可以向该面板提供各种不同的查询。它们可能是从表或视图中选择的简单查询,也可能是用户使用复杂的联接和其他表达式自行定义的复杂查询。我正在尝试修改我的数据面板,以便如果用户选择一条记录,然后对表进行排序,我会找到该记录现在所在的页面,移动到该页面,然后重新选择该记录。

我已经解决了大部分问题,但我无法找到要移动到的页码。我最初只是简单地循环遍历数据面板中的行,但由于分页的原因,事实证明,页码越大,效率就越低。相反,我决定直接通过 SQL 来完成此操作,这就是我现在陷入困境的地方。

我决定,如果我可以通过运行产生结果的相同查询找到所选行的行号,我就可以计算出我需要移动到的最终页码并直接跳转到该页面。我获取了运行以生成结果的查询,并增加了一个变量以获取行号。

原来的查询是

select *
from table_a
order by column_c desc
Run Code Online (Sandbox Code Playgroud)

修改后的行号查询变成了

select *, (@rownum := @rownum + 1) as rownum
from
(select @rownum := 0) rn
, (
  select *
  from table_a
  order by column_c desc
) data
Run Code Online (Sandbox Code Playgroud)

此时我正在选择所有记录。然后,我包装了上面的查询并选择了记录与我选择的记录匹配的最小行,如下所示

select min(rownum)
from
(  
  select *, (@rownum := @rownum + 1) as rownum
  from
  (select @rownum := 0) rn
  , (
    select *
    from table_a
    order by column_c desc
  ) data
) wrapper
where
  primarykeyfield1 = ?
  and primarykeyfield2 = ?
Run Code Online (Sandbox Code Playgroud)

起初这似乎有效。然而,在测试过程中,我发现如果我对一个不够唯一的字段进行排序(例如,1000 条记录在该字段中都具有相同的值),它就会停止工作。我做了一些挖掘,发现每次运行查询时上面的代码都会返回不同的 rownum 。

经过一些额外的挖掘,我发现如果运行以下查询,我会得到我想要的结果

select * from table_a order by column_c
Run Code Online (Sandbox Code Playgroud)

但如果我只是像这样包装该查询

select * from (select * from table_a order by column_c)
Run Code Online (Sandbox Code Playgroud)

每次运行查询时,记录的顺序都会发生巨大变化。这解释了为什么行号正在改变,因为它实际上正在改变。但是,我无法弄清楚为什么仅通过包装查询就会改变顺序。我已经在其他数据库引擎中完成了此操作,因此我认为它与 MySql 特别有关,但我无法找到信息来解释原因。我的假设是,当包装在这样的查询中时,排序依据要么不应用,要么行为不符合预期。

接下来,我尝试将 rownum 计数直接移动到主/基本查询中,如下所示

select *, (@rownum := @rownum + 1) as rownum
from (select @rownum := 0) rn, table_a
order by column_c desc
Run Code Online (Sandbox Code Playgroud)

单独运行此查询会创建正确的行号。但是,由于我需要找到所选记录的特定行号,因此我必须像这样包装该查询

select min(rownum)
from (
  select *, (@rownum := @rownum + 1) as rownum
  from (select @rownum := 0) rn, table_a
  order by column_c desc
) data
where
  primarykeyfield1 = ?
  and primarykeyfield2 = ?
Run Code Online (Sandbox Code Playgroud)

一旦我这样做,排序依据似乎就被忽略了,它按照记录在表中出现的顺序(而不是它们在基本查询中的顺序)对事物进行计数。

我感兴趣的是了解数据集排序在打包时未正确应用的根本问题,以及用于查找特定记录所在页码的潜在其他解决方案。

请注意,我在最终外部查询中使用 min ,因为最终用户可能会选择多行,并且所有这些行都会进入最终的 where 子句。所以我想找到最低的行号并移动到该页面。

Rez*_*mun 5

我的目的已经解决了:)所以,如果有人觉得合适,我会在这里发帖:

SELECT d.myRowSerial
FROM (
    SELECT *, @rownum:=@rownum + 1 AS myRowSerial 
    FROM myTable, (SELECT @rownum:=0) AS nothingButSetInitialValue 
    WHERE 1=1 -- Optional: filter if required, otherwise, omit this line;
    ORDER BY AnyColumn -- Apply the order you like; 
) d
WHERE d.myColumn = 'Anything'; -- If you like to limit it to only
-- for any specific row(s), similar to the *MAIN query.
Run Code Online (Sandbox Code Playgroud)

如果您还需要可用于确定分页偏移值的页码,则只需更改上面的第一行,如下所示:

SELECT d.myRowSerial, FLOOR((d.myRowSerial-1)/10) AS pageNumber
-- Say, 10 is per page;
Run Code Online (Sandbox Code Playgroud)

第 1 页的 pageNumber==0,第 2 页的 pageNumber==1,依此类推......