MySQL - Fetching more records when ordered by integer - php

So, I'm writing an application to fetch records from the database, and my client has asked if I could sort the data by area. I've got the following query:
SELECT
*
FROM
customers
WHERE
account_type != 'x'
AND
account_type != 'tor'
ORDER BY
area ASC,
id ASC
LIMIT 30
The query returns 30 rows worth of data, all with an area value of 1.
I've got an AJAX query set up to fetch another 30 rows, however as I am ordering the data by area, I am unable to just fit a simple range string to my query as shown in the example below:
...
AND
id > 30
...
How would I write a query that would collect the next 30 records from the database?
Also, there is a record with an area value of 0. This is not shown as the first record in the list. Why is this? And how can I fix this?
Thanks

First, combine the where conditions into a single not in:
SELECT c.*
FROM customers c
WHERE account_type NOT IN ('x', 'tor')
ORDER BY area ASC, id ASC
LIMIT 30;
Then, for the next set, use:
SELECT . . .
OFFSET 30
LIMIT 30
This assumes that id is unique in the table. That is important, because that makes the sort stable.

Have a look at the the SELECT query documentation:
https://dev.mysql.com/doc/refman/5.7/en/select.html
[LIMIT {[offset,] row_count | row_count OFFSET offset}]
In summary, just limit returns you x records. With the offset you can set a starting position, basically allows you for paging.

MySQL LIMIT take an optional parameter offset, so you could send in a parameter telling where to start when picking the 30 results you want
SELECT
*
FROM
customers
WHERE
account_type != 'x'
AND
account_type != 'tor'
ORDER BY
area ASC,
id ASC
LIMIT 30, 30
Should give you the next 30 rows starting from row 30

Related

Get last record id from set of records in mysql query without fetching all records

I have a query that fetches a set of records as shown:
select id
from wallactions
where status=1 and created > DATE_ADD(NOW(),INTERVAL -1 DAY)
order by id desc LIMIT $priorRecordsCnt
The LIMIT variable $priorRecordsCnt changes often and can grow very large. It's necessary because i need to know the last id in that set of records based on the $priorRecordsCnt count value.
The problem is, I need to only access the last id in this set, as shown:
$last=array_values(array_slice($result,-1))[0]['id'];
I feel like this is pretty expensive to just get the id of the last record in the set.
Is there a way to optimize this query so it uses the count variable $priorRecordsCnt but i don't need to fetch all the records just to obtain the last value?
The limit clause takes two arguments - an optional offset and the row count. Instead of using $priorRecordsCnt as the record count, you should use it as the offset, and limit the record count to 1:
select id
from wallactions
where status=1 and created > DATE_ADD(NOW(),INTERVAL -1 DAY)
order by id desc LIMIT $priorRecordsCnt, 1
-- Here ---------------------------------^

How do I skip one row in an SQL query?

I'm listing products from my database where I select the latest product as a big feature. The rest are sorted by latest product.
So I have two querys which looks like this.
SELECT * FROM products ORDER BY product_id DESC LIMIT 1
and
SELECT * FROM products ORDER BY product_id DESC LIMIT 4
However... This makes the latest product appear twice in my current layout. (The feature).
How do I tell the second query to skip the latest entry?
We can specify the LIMIT clause to start at second row instead, and then fetch next 4 rows.
SELECT * FROM products ORDER BY product_id DESC LIMIT 1,4
Syntax is:
[LIMIT {[offset,] row_count | row_count OFFSET offset}]
The LIMIT clause can be used to constrain the number of rows returned
by the SELECT statement. LIMIT takes one or two numeric arguments,
which must both be nonnegative integer constants With two arguments,
the first argument specifies the offset of the first row to return,
and the second specifies the maximum number of rows to return.
The offset of the initial row is 0 (not 1):

How to get the data before the max id

I'm doing an info system that has announcements, so I wanted to get the data from announce table, first should be the one with max id of course since it is the latest announcement and here is my code for it:
SELECT image FROM announce where id=(SELECT max(id) FROM announce);
Now I wanted to get the data before the max id and I'm using this code here:
SELECT image FROM announce where id=(SELECT max(id)-1 FROM announce);
But it only works if there are no deleted rows,if there are some deleted rows it doesn't work like max id is 10 and the id's 9,8,7 are deleted. That means the present id's are: 1,2,3,4,5,6,10, how will I be able to get the data in the id 6,5,4,3,2,1?
If you ORDER the query by descending order (DESC), and have an OFFSET of one (OFFSET 1), you would get the second to last row. And offset of two would give the row before that, and so on. This also uses LIMIT 1, so we just get one row. LIMIT 1, 1 is the same as LIMIT 1 OFFSET 1.
SELECT image
FROM announce
ORDER BY id DESC
LIMIT 1, 1
MySQL on SELECT statements
You can just use one query with order by and limit instead of the two queries you use:
select image
from announce
order by id desc
limit 2
In case you want to query them separately, you can change limit 2 to limit 1, 1 for you second query to work as you wish.

Select count giving zero rows

The table have 11 rows
Query
SELECT COUNT(*) FROM `zars_all` ORDER BY id DESC LIMIT 9,9
Result
Zero Rows, even there are two rows having id 10 and 11
Query
SELECT * FROM `zars_all` ORDER BY id DESC LIMIT 9,9
Result
Two Rows having id 10 and 11
I have tried using column names as value in Count but it does't help. Any help is appreciated and please tell me if I am doing anything wrong here.
Your first sentence SELECT COUNT(*) returns an integer.
That means that the trailing LIMIT 9,9 is setting a minimum of 9 elements and a maximum of 9 elements.
Let’s examine the LIMIT offset, count clause parameters:
The offset specifies the offset of the first row to return.
The count specifies the maximum number of rows to return.
Your offset is out of bounds, that is why you get no rows.
Please remove that and leave it like:
SELECT COUNT(*) FROM `zars_all` ORDER BY id DESC
Waqas,
LIMIT cannot be applied directly along with COUNT instead change your query like
SELECT count(*) FROM (select * from zars_all limit 9,9) as a"**;

How can I get the offset of a particular row in MySQL?

I'm trying to make an image database which does not keep a consistent record of ID's. For example it might go 1,2,6,7,12, but as you can see that is only 5 rows.
Inside the table I have fileid and filename. I created a PHP script to show me the image when I give the fileid. But if I give it the ID 5 which does not exist I get an error. That's fine as I want an error for that, but not for users who will browse through these images using forward and back buttons. The forward and back buttons would need to retrieve the true fileid which comes after the given ID. Hopefully that makes sense.
This is how I imagine the code to look like:
SELECT offset( WHERE fileid=4 )
That would give me the offset of the row where fileid is equal to 4. I think this is easy enough to understand. The reasons I need this are for creating the forward and back button. So I planned to add 1 or take 1 from the offset which gives me the new ID, and the new filename. That way when users browse it will skip the dead ID values automatically, but it will give an error when giving a false ID.
Going up:
SELECT * FROM table WHERE id > 'your_current_id' ORDER BY id LIMIT 1;
Going down:
SELECT * FROM table WHERE id < 'your_current_id' ORDER BY id DESC LIMIT 1;
ps: it is better to make LIMIT 2, so that you can see that you are at the first or at the last records in the database when only one record is returned.
If your results are ordered by x, ascending, the following will give you your current offeset in the table:
SELECT COUNT(*) FROM tablename WHERE x < x_of_your_current_item;
If you just want to SELECT the next or previous row, you can skip having to do two queries by just directly selecting one row:
SELECT * FROM tablename WHERE x > x_of_your_current_item ORDER BY x LIMIT 1;
will give you the next item (and similarly < and adding DESC to the order-by would give you previous).
You can use offset. Initially set offset as zero.
First time your query will be
SELECT * FROM TABLE order by table_id LIMIT 0,1
and next
SELECT * FROM TABLE order by table_id LIMIT 1,1
..
and so on
This way one will get records from the beginning till the end.
Now about back and forward buttons.
Back Button: First time or whenever offset is zero disable back button
Forward Button:
when you query for a current record you check for the next record too
i.e. after this query
SELECT * FROM TABLE order by table_id LIMIT 0,1 fire a query like this
SELECT * FROM TABLE order by table_id LIMIT current_offset+1,1 and check if the query produces any results if it produces a result then set a boolean say next = TRUE else next = FALSE;
Using this boolean enable or disable Forward button.
One more thing on click of back button send the offset as current_offset - 1 and for forward button current_offset + 1
I hope this helps. I just came across this and thought of this solution.
SELECT * FROM table WHERE ... ORDER BY id DESC LIMIT 50,10;
SELECT * FROM table WHERE ... ORDER BY id DESC LIMIT 60,10;
SELECT * FROM table WHERE ... ORDER BY id DESC LIMIT 70,10;

Categories