我正在使用一个通用数据面板,它可以为该面板提供各种不同的查询。它们可能是从表或视图中选择的简单查询,也可能是用户使用复杂连接和其他表达式定义自己的复杂查询。我正在尝试修改我的数据面板,以便如果用户选择一条记录,然后对表格进行排序,我会找到该记录现在所在的页面,移动到该页面,然后重新选择该记录。
我已经解决了大部分问题,除了我无法找到要移动到的页码。我最初只是简单地遍历数据面板中的行,但由于分页,这被证明是非常低效的,页码越大。相反,我决定直接通过 SQL 来执行此操作,这就是我现在卡住的地方。
我决定,如果我可以通过运行产生结果的相同查询来找到所选行的行号,我可以计算我需要移动到的最终页码并直接跳转到该页。我使用运行的查询来生成结果,并增加一个变量来获取行号。
原来的查询是
select *
from table_a
order by column_c desc
修改后的带有行号的查询变成了
select *, (@rownum := @rownum + 1) as rownum
from
(select @rownum := 0) rn
, (
select *
from table_a
order by column_c desc
) data
在这一点上,我正在选择所有记录。然后我包装了上面的查询并选择了记录与我选择的记录匹配的最小行,如下所示
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 = ?
起初,这似乎奏效了。然而,在测试期间,我发现如果我对一个不够唯一的字段进行排序(例如,1000 条记录在该字段中都有相同的值),它就会停止工作。我做了一些挖掘,发现每次运行查询时,上面的代码都会返回不同的 rownum。
经过一些额外的挖掘,我发现如果要运行以下查询,我会得到我想要的结果
select * from table_a order by column_c
但是如果我像这样简单地包装那个查询
select * from (select * from table_a order by column_c)
每次我运行查询时,记录的顺序都会发生巨大变化。这解释了为什么行 num 会发生变化,因为它实际上正在发生变化。但是,我无法弄清楚为什么仅通过包装查询就会改变顺序。我已经在其他数据库引擎中做到了这一点,所以我认为它与 MySql 特别有关,但我无法找到解释原因的信息。我的假设是,当包裹在这样的查询中时,order by 要么不应用,要么行为不符合预期。
接下来,我尝试将 rownum 计数直接移动到主/基本查询中,如下所示
select *, (@rownum := @rownum + 1) as rownum
from (select @rownum := 0) rn, table_a
order by column_c desc
单独运行此查询会创建正确的行号。但是,由于我需要找到所选记录的特定行号,因此我必须像这样包装该查询
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 = ?
一旦我这样做,order by 似乎就被忽略了,它按照记录出现在表中的顺序计算事物,而不是它们在基本查询中的顺序。
我有兴趣了解数据集排序在打包时未正确应用的潜在问题,以及用于查找特定记录所在页码的潜在其他解决方案。
请注意,我在最终的外部查询中使用 min ,因为最终用户可能会选择多行,并且所有这些行都会进入最终的 where 子句。所以我想找到最低行 num 并移动到该页面。