I am working with a generic data panel that can have a variety of different queries feeding that panel. They might be simple queries that select from a table or view, or complex ones that users define themselves with complicated joins and other expressions. I am trying to modify my data panel so that if a user selects a record, then sorts the table, I find the page that record is now on, move to it, and then reselect the record.
I've got most of this worked out, except I am having trouble finding the page number to move to. I originally simply looped over the rows in the data panel but because of paging, this proved to be very inefficient the larger the page number became. I instead decided to do this directly through SQL which is where I am stuck now.
I decided that if I could find the row num of the selected row by running the same query that produced the results I could calculate the final page number that I need to move to and jump right to that page. I took the query that was run to generate the results, and incremented a variable to get the row numbers.
The original query was
select *
from table_a
order by column_c desc
And the modified query with row numbers became
select *, (@rownum := @rownum + 1) as rownum
from
(select @rownum := 0) rn
, (
select *
from table_a
order by column_c desc
) data
At this point I'm selecting all records. I then wrapped the above query and selected the minimum row where the record matched my selected record like so
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 = ?
At first this appeared to be working. During testing however, I discovered that if I sorted on a field that was not sufficiently unique (e.g. 1000 records all had the same value in this field) it stopped working. I did some digging and found that the above code would return a different rownum every time the query was run.
After some additional digging, I found that if were to run the following query, I would get the results I wanted
select * from table_a order by column_c
But if I simply wrapped that query like so
select * from (select * from table_a order by column_c)
The order of the records changed drastically every time I ran the query. This explains why the row num was changing because it is in fact changing. However, I can't figure out why the order would change simply by wrapping the query. I've done this in other database engines so I assume it has to do with MySql specifically but I have been unable to locate information to explain why. My presumption is that the order by is either not applied when wrapped in query like this, or the behavior is not as expected.
Next, I attempted to move the rownum count directly into the main/base query like so
select *, (@rownum := @rownum + 1) as rownum
from (select @rownum := 0) rn, table_a
order by column_c desc
Running this query by itself creates the correct row numbers. However, since I need to find the specific row num of the selected record I must wrap that query like so
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 = ?
As soon as I do this, the order by seems to be ignored and it counts things in the order that the records appear in the table, instead of the order they are in in the base query.
I'm interested in both understanding the underlying issue with the data set sort not being applied correctly when wrapped up, as well as potential other solutions for finding the page number that a specifc record resides on.
Note, I am using min on the final outer query because ultimately the user may select multiple rows, and all of those rows go into the final where clause. So I want to find the lowest row num and move to that page.