MySql paginated results, find "page" for specific result - mysql

I have an application using a MySql database which is displaying a paginated list of records, to which to which the user is able to add new ones. I know how to get paginated results using LIMIT etc, but the question is how to go a specific page when adding a new record. If the page size is 20, and the user is viewing the first page, and they add a record which is 23rd (out of say 100), how do we determine which page to show the user.
So, essentially, given a page size and a specific record, how do I determine which "page" to show out of the pages. The total pages do NOT include all of the records for the table they belong to, but the criteria for getting them is static.
Edit:
I should have been more specific. The records contain a unique ID field and a string name field. The resultant records are sorted by the name alphabetically. Also, this is a java application.
The only thing I can think of is to select all the desired records sorted by name and then some how find the position in those results of the specific record. From that position the page number could be easily calculated since we know the page size, but I'm not sure if they is MySql syntax for getting the position of a record in the results.
The "dumb" solution would be to just grab them all and then in the application code (java), determine the specific records position in all the results. But is seems like their must be a more efficient way.

SELECT COUNT(*) as CNT FROM tbl WHERE name < (SELECT name FROM tbl WHERE id = 42)
After that you just divide CNT value to the amount rows per page and round (Math.floor()) it
Or you can even do that in sql:
SELECT FLOOR(COUNT(*) / 20) AS page_number ...

Related

Need to count records in rdl with page breaks

I have a report that uses page breaks to show 1 record per page. I need to get a count of the records (outside of looking at the page number) and show it at the bottom of my table on each page. The page break is seperating my data groupings making the count always return 1.
The page break is on a group using the expression =Ceiling(Rownumber(Nothing)/1)
I am attempting to get the count of records by counting the occurences of the identifier field.
Is this even possible or am I just going about the solution wrong?
You can set a placeholder with the following expression =CountRows("YourDataSet")
This will count all of the rows that your data set returns.

Mysql store position in ordered query, in database to accommodate point lookups

I have the following situation.
I have a leaderboard that is backed by a mysql table.
An entry in the table table will look like.
username | score
When we are displaying the scoreboard we query for all entries sorted by score. Then we assign the users positions based their position based in the result set.
For example if we query for the table and there are 3 results.
We know result 1 is 1st position, result 2 is second position etc.
Users can submit scores and there is nothing new to compute till we query for the leaderboard.
However this leads to the problem where, we can't tell a single user what position they are in without querying for the entire database.
Is there a way for mysql to store this information and make updates of new users fast?

Identify row index of specific row within dataset by reference to the principal key

I have a table "documents", with an id column, which is the principal key. The table has numerous other fields and users can view the table sorted by reference to many of these fields. The table data is displayed within a virtual tree control which requests only the data it requires for the current client area of the tree.
Say my document table had the following structure and data (it doesn't, but the simple eg below is hopefully suffucient to illustrate)
id description date_of_doc
----------------------------------
1 Doc 1 10/05/1987
2 Doc 2 11/06/1988
3 Doc 3 12/07/1989
4 Doc 4 13/08/1990
5 Doc 5 14/09/1991
6 Doc 6 15/10/1992
My virtual control loads the date in id order is as per the default table order.
However, the control allows you to click on headers which are called "description" and "date_of_doc". Clicking on these headers changes the order in which the data is displayed in the control. Click the same header twice and it will sort descending. I issue a new query to get the data with an "ORDER BY" command depending on what header has been clicked.
So if I am sorting by date_of_doc and it is descending then the new position of id 2 is in fact 5. Having sorted my user then clicks on the "Find by ID" link to find the document with the id "2". I now need to take him to the correct node within my tree control to find this document. From the simple dataset above we can work out that the new index of this position within the tree is 5. But how do I do that with a query taking into account the Order by clause.
Currently I am selecting the id field for every row in the table using the same Order by and then iterating through the query result until I can match the document id with the id requested by the user. There is nothing wrong with this query in the sense that it gets me the correct position, it just strikes me as grossly inefficient especially as I need to work with large tables.
What I am looking for is a query which is something like
SELECT row_num FROM documents WHERE id=12345 ORDER BY date_of_doc
However, the control allows you to click on headers which are called
"description" and "date_of_doc". Clicking on these headers changes the
order in which the data is displayed in the control. Click the same
header twice and it will sort descending. I issue a new query to get
the data with an "ORDER BY" command depending on what header has been
clicked.
This is not very efficient as it needlessly hits the DB everytime someone tries to sort columns. You can retrieve data once per usersession and either cache the data on the Web Servers Memory and sort it in memory. Or use some client side sorting techniques using many javascript libraries ... Iam not an expert on these techniques but you should be able to find help on this topic as it is a very common scenario. Also you haven't mentioned what technology stack you are using to build your web app. C# asp.net, java , php, etc ...
So assuming that we are sorting in memory the only other call to the db would be to fetch the document for the particular requested document.
That said for your immediate need to avoid iterating rows to find
To do that you can write a Stored procedure that takes the DocID and returns the recordset like so ( just pseudocode may need to tweak it for your actual scenario ) :
Create GetDocDetailsByID
(
#id int
)
Begin
select id, description, date, ....
from yourtablename
where id = #id
End
You should have that doc id in your application at run time when the user performs a button click or hits a hyperlink. Call the above SP with that ID. this part is platform specific. So let me know what is your front end platform and we can see if that needs tweaking.

query to aggregat data by day to generate charts - rows unkown

I started building a search engine monitor. I'm pulling data from the google rest api into a mysql database with the following fields: date, search-keyword, domain, url, position.
Now I got into trouble querying and outputting the data for charting. The results go up and down, new results from google come into the list which haven't been there on the first day. However for charting I have to assign the first days at least blank values to output a chart.
What I do right now: First I select every domain showing up in the period. Lets say the for the keyword searchengine I get the domains wikipedia.org, ixquick.com, yahoo.com, searchenginewatch.com When I make another request for ever domain to query an array of rankings grouped by day. leading to the ...
Problem: Is where any query (mysql/nosql) which returns for each day an average and if where is no row a default value e.g. blank?
Result should look like:
dates={01/01/2014,02,03,04,05,06,07,08,...,31}
wikipedie={1,1,1,1,1,1,1,1,...,1}
yahoo = {"","",7,5,3,3,3,...,3}
You can create a date table, select the date range you'd like, and outer join your data to it, filling in 0s for values that do not exist for a given term/date.
Edit:
Some more details.
1) Create a table that has a row for every date +- 10 years (or whatever is appropriate). You can make this one column if you'd like, or many columns (date, month, year, etc.). The second approach makes this extensible if you want to summarize by various rollups in the future.
2) Outer join your table to the date table and use a NVL statement to coerce any null averages to 0.
3) Profit!
If your results are grouped by date, how can MySQL know there's (for example) 31 days in that month?
On the other hand, you can somehow fill the holes in PHP by loop through the array and fill a zero if the value does not exist.

MySQL: Use aggregate result in further calculation

I'm currently working on writing report generators. For one report I need to do a breakdown by a given characteristic (supplier, logging user, language, etc which for each row includes the name of the characteristic I'm interested in, the number of items that match that characterastic, and the percentage of total items this figure represents. The first two aren't a problem, the third is.
For example, to get a breakdown by language I'd be using a query like this.
SELECT lang_id,
COUNT(IF(open=TRUE,1,NULL)) AS lang_total
FROM table
GROUP BY lang_id;
This gives me the number of items per language.
I can get the total number of items in the table and store it in a variable simply enough with a plain count.
SELECT #totalOpen:=COUNT(*) FROM table WHERE open = TRUE;
Now I want to add a third column, which is the figure in lang_total divided by the value in #totalOpen multiplied by 100 (in other words, the percentage of all items that fit the criteria). Something along the lines of the following:
This is the bit I'm having trouble with, as because as far as I can tell you can't use aggregate columns in calculations.
SELECT lang_id,
COUNT(IF(open=true,1,NULL)) AS lang_total
(lang_total/#totalOpen)*100 as lang_percent
FROM table
GROUP BY lang_id;
I'm sure that there must be a way of doing this in MySQL, but I've not been able to track it down. Can anyone help out with this?
I read this question now for the first time. I know that probably it's too late to be useful for you but I would have solved in this way.
select lang_id,
sum(if(open= true,1,0)) as lang_total,
coalesce(sum(if(open= true,1,null)) / #r,0) as percentage
from table,(select #r:=count(*) from table where open = TRUE) as t
group by lang_id;