Does MAX(expr) have a limit - php

I have a table with 25,000 entries and growing. In the code, there is this line
$result = sqlQuery("SELECT MAX(pid)+1 AS pid FROM patient_data");
$newpid = 1;
if ($result['pid'] > 1) $newpid = $result['pid'];
This line returns an error from the database that says duplicate record at 10000.
What this line of code is supposed to be doing is to retrieve the last entry for the pid column and then the next lines of code add one to create the next entry in the table.
From my research MAX() is a summing tool, not a tool used to retrieve the last value entered into a table.
https://dev.mysql.com/doc/refman/5.7/en/group-by-functions.html#function_max
Looking for some clarification on how to use this properly. I can't seem to find a clear answer. Hoping some you more experienced developers can help steer me in the right direction.

Since the table already has the ID column auto incremented and there is only one of those allowed per table in MySQL. I had to resort to a different method.
Decided to go with the get the last record this way.
$result = sqlQuery("SELECT id AS pid FROM patient_data ORDER BY id DESC LIMIT 1");
$newpid = 1;
if ($result['pid'] > 1) $newpid = $result['pid'] + 1; //Changed by Sherwin
setpid($newpid);

Related

How to limit mysql rows to select newest 50 rows

How to limit mysql rows to select newest 50 rows and have a next button such that next 50 rows are selected without knowing the exact number of rows?
I mean there may be an increment in number of rows in table. Well I will explain it clearly: I was developing a web app as my project on document management system using php mysql html. Everything is done set but while retrieving the documents I mean there may be thousands of documents.
All the documents whatever in my info table are retrieving at a time in home page which was not looking good. So I would like to add pages on such that only newest 50 documents are placed in first page next 50 are in second and so on.
But how come I know the exact number of rows every time and I cannot change the code every time a new document added so... numrows may not be useful I think...
Help me out please...
What you are looking for is called pagination, and the easiest way to implement a simple pagination is using LIMIT x , y in your SQL queries.
You don't really need the total ammount of rows you have, you just need two numbers:
The ammount of elemments you have already queried, so you know where you have to continue the next query.
The ammount of elements you want to list each query (for example 50, as you suggested).
Let's say you want to query the first 50 elements, you should insert at the end of your query LIMIT 0,50, after that you'll need to store somewhere the fact that you have already queried 50 elements, so the next time you change the limit to LIMIT 50,50 (starting from element number 50 and query the 50 following elements).
The order depends on the fields you are making when the entries are inserted. Normally you can update your table and add the field created TIMESTAMP DEFAULT CURRENT_TIMESTAMP and then just use ORDER BY created, because from now on your entries will store the exact time they were created in order to look for the most recent ones (If you have an AUTO_INCREMENT id you can look for the greater values aswell).
This could be an example of this system using php and MySQL:
$page = 1;
if(!empty($_GET['page'])) {
$page = filter_input(INPUT_GET, 'page', FILTER_VALIDATE_INT);
if(false === $page) {
$page = 1;
}
}
// set the number of items to display per page
$items_per_page = 50;
// build query
$offset = ($page - 1) * $items_per_page;
$sql = "SELECT * FROM your_table LIMIT " . $offset . "," . $items_per_page;
I found this post really useful when I first try to make this pagination system, so I recommend you to check it out (is the source of the example aswell).
Hope this helped you and sorry I coudn't provide you a better example since I don't have your code.
Search for pagination using php & mysql. That may become handy with your problem.
To limit a mysql query to fetch 50 rows use LIMIT keyword. You may need to find & store the last row id(50th row) so that you can continue with 51th to 100th rows in the next page.
Post what you have done with your code. Please refer to whathaveyoutried[dot]com
check this example from another post https://stackoverflow.com/a/2616715/6257039, you could make and orber by id, or creation_date desc in your query

What is the difference between while and between, and what is the better choice in my case?

I have a table that have hundreds of rows, and i want to get specific rows, I used the LIMIT and between id and id
In my application i have two text inputs, one is for START NUMBER and one is for END NUMBER, When i use the LIMIT i need to tell the user to make the right calculation to get the right start and end
So for example if i have a table of 3000 rows, and i want to select 100 rows above 2000 the query will be :
Select * from table LIMIT 2000,100
This will select 100 rows above 2000
The between method :
In the between method, i'm running a while function on all the table and i'm using IF statement to get the right id's here is what i'm doing :
Select * from table
$datastart = $_POST["datastart"];
$dataend = $_POST["dataend"];
$firstid = 0;
$lastid = 0;
$varcount6=1;
$sql = "select ID from users_info";
$sqlread = mysqli_query($conn,$sql);
while($row = mysqli_fetch_assoc($sqlread)){
if($datastart==$varcount6){
$firstid = $rowdirstid["ID"];
}
if($varcount6>=$dataend){
$lastid = $rowdirstid["id1"];
break;
}
$varcount6++;
}
So now i have the first id and the last id of the table, next i use another sql query :
Select * from table where id between $firstid and $lastid
Both worked
My question is: what should i use if i'm loading huge amount of data each time ?
Should i go with while ? or the LIMIT will make the job done ?
To begin with, you should never use PHP to get the data required, stick to doing that solely in SQL, as PHP is never needed.
The limit query you're using will not cut it for what you're trying to do, as it will not care what id's the entries has, so, if your id's are not 100% consecutive, you will not get the desired result.
You should use the between query you display at the bottom of your post.
But, since you haven't provided your full code I cannot say wether or not you sanitized that input, but that is always a good thing to keep in mind. It's preferable to use parameterized queries instead aswell.
If your sure the ID are consecutive, use SELECT * FROM t WHERE id BETWEEN a AND b ORDER BY ID ASC
If you use LIMIT, the SQL Engine have to scan and order all the first results.
(and index the id field)

MySQL remember last position

I have made a small app where a table of data is presented to the user. The data can be sorted by different column headers and filter using inputs.
When the user clicks on a row it opens a small popup which contains two arrows for going to the next and previous record, in the same order as they appear in the table.
Originally I had (for "previous" as an e.g.):
SELECT ed.id
FROM entity_details AS ed, users
WHERE ed.id > ?
AND ed.typeRef = ?
AND ed.ownerRef = users.id
$filter
$SQLOrder LIMIT 1
Which works fine if the table is sorted by ed.id, but will not work properly if sorted by another column e.g. ed.name, because the next alphabetical name might have a much higher or lower id.
FYI $filter could be something like:
AND branchRef = 2
and $SQLOrder could be:
ORDER BY ed.name DESC
What do I need to do to make it cycle through the records properly, respecting current order and record position?
All the sorting and filtering parameters come through over AJAX, e.g:
$JSON->selectedbranch ;
I've come to the conclusion that all I need to know is how to start the query from a row with column X containing value Y, is that possible?
You should store the number of the row you displayed, not the ID. Then just do the ordering in SQL as your application requirements imply, then apply the knowledge contained here:
Skipping first n results in MySQL
To simplify the job, and to make this answer usable for future SO dwellers:
SELECT ed.id
FROM entity_details AS ed, users
WHERE ed.typeRef = ?
AND ed.ownerRef = users.id
$filter
$SQLOrder
LIMIT $currentRowNum,1
This scheme smells however: using this to navigate your rows implies a SQL query for each navigation action. That might have an bad effect on your response time...
PHP's mysql_data_seek function may helps.
mysql_data_seek
I found it, seeing that other guys answer gave me an idea, but his answer has disappeared :(
For the next button I have:
$result = $dbh->prepare("SELECT ed.id
FROM entity_details AS ed, users
WHERE $WHERE < ?
AND ed.typeRef = ?
AND ed.ownerRef = users.id
$filter
ORDER BY ed.name DESC LIMIT 1") ;
$WHERE is just the column name "ed.name".
I just have to sort out the dynamics for $where and the ORDER BY clause and it'll be good to go.
Thanks for every ones input!

Mysql COUNT(*) in a foreach loop, to get row numbers. Performance issues?

I want to return the row number of a particular row (so how many rows before a given row).
Now the problem is the PRIMARY_KEYs are not sequential, so there are 'gaps' inside them, because sometimes I have to DELETE rows.
id = 1
id = 2
id = 5
id = 9
id = 10
So the only option to get the row number is to use a COUNT(*):
SELECT COUNT(*) FROM table WHERE id < selected_row_id;
But for a given page I have to perform this operation multiple times.. so one solution is to use a foreach loop, like:
foreach($foo as $item){
mysql_query("SELECT COUNT(*) FROM table WHERE id < $item['id']");
//...
}
But I think it's not optimal...if one have thousands of rows and 80-100 iterations for the above foreach.
Another solution would be to rebuild the entire id column after DELETING a row.. but because foreign constraints / references I think this isn't a good step, too.
So if COUNT(*) in a foreach is not viable, then is there anyone who faced this type of problem, what would be the optimal solution?
Thanks for your time, and sry for my bad english.
I recently had a similar issue where, for a given set of results, I wanted to know the position # of a specific result in that set.
There's an elegant solution which will give you sequential row numbers for a resultset, based on internal incrementation of a variable
See http://craftycodeblog.com/2010/09/13/rownum-simulation-with-mysql
Hope that helps you out
Instead of rebuilding the id column after each delete or insert, how about just adding a new column to the table to store the data you need?
I think you want to try this:
SELECT parent.Id, count( DISTINCT (child.Id) ) AS previous
FROM table AS parent, table AS child
WHERE child.Id < parent.Id
I don't think it is efficient from a database perspective, but should be better than iterating from code. Caveat is that you need to build the required php code since I am not proficient at that, but should be easy.
There are a couple ways to improve this
You can sort $items by ID, then keep track of the number of rows above the last item, and add to this the number of rows between the current item and the last item: $last_id <= id AND id < $item['id']
Context switching is expensive. It is better to grab all the IDs in a single query, then process the information in PHP.

adding 1 to last row of mysql table

Hi I'm trying to select the last ID in my table then add 1 to the value. I am selecting the last row just find the problem is that I'm having problems with the +1 I think this is because it's an array but I'm not sure.
$result = mysql_query("SELECT `id` FROM `users` ORDER BY `id` DESC LIMIT 1");
$row = mysql_fetch_row($result);
$pin = $row[0]+1;
echo ($row[0]); //returns the id
echo ($pin); // returns null
Any thoughts on this would be great.
Try this:
SELECT max(id) + 1 from users
But if you are doing an insert, just grab mysql_last_insert_id() to find out what was just inserted. Otherwise you will have issues with concurrency.
Your id is setup as AUTOINCREMENT correct? You should never never never never ever assign the primary key yourself. this is the db servers job.
You should use mysql_insert_id().
printf("Last inserted record has id %d\n", mysql_insert_id());
That will display the most recently inserted id.
There are several possible solutions. The easiest given the code you already have above may be:
$pin = intval($row[0])+1;
That said, there are definite improvements/optimizations to be made in the code that other answers here touch on. But if you're looking for the shortest path from what you have to what you want, that one change might be it.
You can not reliably determine the next inserted id before the actual insert takes place. The last record may have been deleted, but that does not change the auto_increment value of the table. Also, if two (or more) concurrent requests happen, both can check the last inserted id and find the same value. When inserting the rows, both will get different ids...

Categories