MySQL remember last position - php

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!

Related

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)

How can I show at least 3 record from mysql using php pdo [duplicate]

ok; this has been frying my brain for hours. I think I might need a sub query, but I'm not that advanced at this kind of thing so any help or pointers in the right direction would be greatly appreciated.
Here's the Query I have....
$query = "SELECT * FROM events WHERE event_type = 'Christmas Listings' AND event_active='Yes' ORDER BY event_date ASC LIMIT 5";
$result= mysql_query($query);
OK... now for the plain english bit on what I want to achieve (to understand what I'm trying to achieve):
I want to check the event type ('event_type') is what I'm getting (ie. Christmas Listings) as there are multiple types in this column.
I want to check the event is active ('event_active') is Yes(the data in this field is Yes/No).
I want to order them by the ('event_date') ASC (the data in this field is yyyy-mm-dd) so they show the latest entry by its date from the DB.
I want to LIMIT (or in some way control the output) the results to only have 5 results displayed when running this kind of query through a WHILE statement.
OK, this all works BUT; when I get to the actual output display, i'm having a shaky output in how many results are actually display... What happens is if I have multiple events which are switched off, as in event_active is 'Off' then its almost like the argument is counting from the all the results that are (including event_active='Off') and consequently not showing how I expect them to display?
Hope this makes sense.... Any help would be gratefully received.
SELECT *
FROM events
WHERE event_type = 'Christmas Listings' AND event_active='Yes'
ORDER BY event_date
LIMIT 0, 5
so your statement is easyer to read..
You shoul use 1 / 0 instead of Yes / no
The Limit does not count all lines!
First step - doing the query including WHERE
Second step - ORDER BY
Third step - LIMIT
If you have set an index on the colum you sort. The sort will stop after 5 lines,
also means - it get faster
The ASC in the ORDER BY command is not necessary, because ASC is default
I am really not sure what you are asking, but LIMIT works as follows:
The LIMIT means that after your query is done, and ALL WHERE statements are processed, only the first 5 are returned.
ALl results where event_active is not 'Yes' will not be shown, and disregarded in everything.
This result is the same as a result where you would do the query without the limit, and just look at the first 5 lines.
That query should be fine. I'd check your data set (or even better, post it!). You might want to look into normalizing the database too. It'll help you out in the future.
The problem, I think, is with your 'event_active'.
MySQL uses 0 and 1 to indicate whether the field is true/false, yes/no, on/off. Try using 0 and 1 in your SELECT statement unless the field type on that field is VARCHAR and you actually are using those words.

sphinx search math operation between fields

Since I'm moving to sphinx search engine to improove my ebsite performance I'm trying to translate the old mysql queries to new sphinx language.
The point is to sort results based on a math operation between votes to my posts and the points given for each vote (going from 1 to 5).
So for example, if i got 3 votes for a post and I got vote 1=5points vote 2=3points and vote 3=2points, my table will contain a field named votes with an integer = 3 (votes=3) and a field with an integer of 5+3+2 (points=10).
Due to this the final rating for such post will be points/votes, in this example it will be 10/3=3,333...
Assuming I'm using the sphinx api to get a list of top rated posts in DESCENDING order, this is the old mysql query i had on my php script:
mysql_query("SELECT * FROM table ORDER BY points/votes DESC LIMIT $start,$stop");
I tried to build a sphinx query, but it is not working and always giving 0 results. Please read tall the // commented lines that describe all the tries I did.
require("sphinxapi.php");
$cl = new SphinxClient;
$index = index;
$cl->setServer("localhost", 9312);
$cl->SetMatchMode(SPH_MATCH_FULLSCAN);
//$cl->SetSortMode(SPH_SORT_EXTENDED, 'IDIV(points,votes) DESC'); //not working
//$cl->SetSortMode(SPH_SORT_EXTENDED, '(points DIV votes) DESC'); //not working
//$cl->SetSortMode(SPH_SORT_EXTENDED, 'points/votes DESC'); //not working
//$cl->SetSortMode(SPH_SORT_EXTENDED, '(points/votes) DESC'); //not working
$cl->setLimits($start,$stop,$max_matches=1000);
$query = "";
Would you please help me out finding what's wrong... thanks.
You will need to use SPH_SORT_EXPR
$cl->SetSortMode(SPH_SORT_EXPR, '(points/votes) DESC');
Firstly you need points and votes to be Attributes, NOT fields. Attributes are stored in the index, can be used for sorting etc. Arithmetic can only be performed on numeric attributes (not strings)
The correct syntax for SPH_SORT_EXPR (assuming you've already got the attributes) would be
$cl->SetSortMode(SPH_SORT_EXPR, 'points/votes');
SPH_SORT_EXPR is ALWAYS descending, so you dont need it DESC on the end.
But rather than have sphinx calculate that ratio every single time, you would porbbaly be better calculating during sql_query and storing it as single number attribute. TIP: store as an integer, not float. Integers are more efficient to sort by.

LIMIT results in MySQL?

ok; this has been frying my brain for hours. I think I might need a sub query, but I'm not that advanced at this kind of thing so any help or pointers in the right direction would be greatly appreciated.
Here's the Query I have....
$query = "SELECT * FROM events WHERE event_type = 'Christmas Listings' AND event_active='Yes' ORDER BY event_date ASC LIMIT 5";
$result= mysql_query($query);
OK... now for the plain english bit on what I want to achieve (to understand what I'm trying to achieve):
I want to check the event type ('event_type') is what I'm getting (ie. Christmas Listings) as there are multiple types in this column.
I want to check the event is active ('event_active') is Yes(the data in this field is Yes/No).
I want to order them by the ('event_date') ASC (the data in this field is yyyy-mm-dd) so they show the latest entry by its date from the DB.
I want to LIMIT (or in some way control the output) the results to only have 5 results displayed when running this kind of query through a WHILE statement.
OK, this all works BUT; when I get to the actual output display, i'm having a shaky output in how many results are actually display... What happens is if I have multiple events which are switched off, as in event_active is 'Off' then its almost like the argument is counting from the all the results that are (including event_active='Off') and consequently not showing how I expect them to display?
Hope this makes sense.... Any help would be gratefully received.
SELECT *
FROM events
WHERE event_type = 'Christmas Listings' AND event_active='Yes'
ORDER BY event_date
LIMIT 0, 5
so your statement is easyer to read..
You shoul use 1 / 0 instead of Yes / no
The Limit does not count all lines!
First step - doing the query including WHERE
Second step - ORDER BY
Third step - LIMIT
If you have set an index on the colum you sort. The sort will stop after 5 lines,
also means - it get faster
The ASC in the ORDER BY command is not necessary, because ASC is default
I am really not sure what you are asking, but LIMIT works as follows:
The LIMIT means that after your query is done, and ALL WHERE statements are processed, only the first 5 are returned.
ALl results where event_active is not 'Yes' will not be shown, and disregarded in everything.
This result is the same as a result where you would do the query without the limit, and just look at the first 5 lines.
That query should be fine. I'd check your data set (or even better, post it!). You might want to look into normalizing the database too. It'll help you out in the future.
The problem, I think, is with your 'event_active'.
MySQL uses 0 and 1 to indicate whether the field is true/false, yes/no, on/off. Try using 0 and 1 in your SELECT statement unless the field type on that field is VARCHAR and you actually are using those words.

Order By DESC/ASC not working within PHP Query

I have this code so far which is within 2 while loops:
mysql_query("SELECT * FROM listing WHERE
(category_id='$category' OR category_id_2='$category' OR category_id_3='$category')
AND listing_status='1' AND listing_type='1' AND listing_id='$listing_id'
ORDER BY overall DESC");
The data is showing exactly what I want, however the ORDER BY simply isn't working. I'm not too sure what it's ordering by. The overall column itself is DECIMAL(12,2).
The values are saved to only 2 decimal places. For instance, in each row it could be 2.56, 2.89. In this case I want the 2.89 to show before the 2.56. However, it's not.
Many thanks in advance.
I believe you are only selecting one element at a time in your query, something like
while(...){
$category = ...;
$listing_id = ...;
// Your query which only returns one result here
}
Then since your query only returns one result it has nothing to sort, and you see the results in the order the queries are executed.
You need to rewrite your query to select all the rows you want in one go instead of having it in a loop if you want ORDER BY to work. Using IN in your query may help you.
Have you tried casting the field as a decimal in the order by?
ORDER BY CAST(overall as DECIMAL) DESC
I have managed to solve the problem.
By implementing the 'overall' column in the first loops table, instead of the second. It orders the data first by overall, and then goes ahead and gathers the other data from the second table.
Many thanks for your help.
Try:
mysql_query("SELECT * FROM listing WHERE
(category_id='$category' OR category_id_2='$category' OR category_id_3='$category')
AND listing_status='1' AND listing_type='1' AND listing_id='$listing_id'
ORDER BY overall+0 DESC");
The query is fine. The problem is probably with how you iterate returned data. Try changing it.
If not, provide us with the whole relevant piece of your PHP code.
I don't know why, but I found out by copying and pasting from phpmyadmin that this worked to solve a similar problem. The ' is changed to ` - dunno if it's important. But definitely ASC worked with the second way.
Important - the have been stripped from the second method, put them around the table name and the column names.
instead of
$sql = "SELECT * FROM 'dczcats' ORDER BY 'first' , 'second' ASC";
I typed this
$sql = "SELECT * FROM `dczcats` ORDER BY `dczcats`.`first` , `dczcats`.`second` ASC";

Categories