Mysql limit when the whole list may change - mysql

I have a query that returns 10 items of a big list. For example:
SELECT * FROM users
WHERE user_is_block = 0
AND user_is_paid = 1
ORDER BY user_post_hour ASC, id ASC"
When I put limit ?, ? to get a part of this list each time, a problem happens. Imagine we get the first 10. The row with id 11, is the first one in the next request. But as we use ORDER BY user_post_hour, the id 11 may go up and become 10. So when second request is sent, we never see id 11.
Any idea?

It might be the problem with datatype soring, again cast your column value to an integer explicitly
SELECT * FROM users
WHERE user_is_block = 0
AND user_is_paid = 1
ORDER BY cast(user_post_hour as unsigned) ASC, id ASC
Use this trick.
SELECT * FROM users
WHERE user_is_block = 0
AND user_is_paid = 1
ORDER BY user_post_hour+0 ASC, id ASC

Related

Is it possible to get the Next and Previous values in an SQL table when you know the Current value?

What I'm trying to do is get the Next and Previous values in SQL.
In this example I'd always know the current value.
This is how my table is laid out.
id
parentID
appID
Name
19410
18371
2da4
name600
19410
18371
4ac0
name24
19410
18371
348e
name441
So my goal is for example get the next/previous value from the current.
So if the current is test2, I'd get test3 back.
I have looked into using offset + limit but I don't think that allows you to select a current starting point.
I cannot store an array as I don't want it to be slow either.
This differs from other questions as I do not have a iterable value as for example name won't always be test1, test2, test3.
My version is 8.0.19 - MySQL Community Server - GPL
For efficiency, you will need INDEX(name) (or some index starting with name)
To get the next row based on "name":
SELECT ...
FROM ...
WHERE name > 'test2'
ORDER BY name ASC
LIMIT 1
For Previous, change 2 things:
SELECT ...
FROM ...
WHERE name < 'test2'
ORDER BY name DESC
LIMIT 1
To get both at the same time:
( SELECT ... FROM ... WHERE name > 'test2' ORDER BY name ASC LIMIT 1 )
UNION ALL
( SELECT ... FROM ... WHERE name < 'test2' ORDER BY name DESC LIMIT 1 )
This will be a lot faster than LEAD and LAG or Cursors.

Order by value decrement to one + mysql

Ex : I have V001, V002, V003, V004 records,
tid is_premium
---- ----------
V001 0
V002 0
V003 0
V004 1
V005 1
How to get records order by below like this,
V001
V004
V005
V002
V003
2nd Ex : I have V006, V007, V008, V009 records,
tid is_premium
---- ----------
V006 0
V007 0
V008 1
V009 0
How to get records order by below like this,
V006
V008
V007
V009
I want to above order in MySQL, I have to write but not possible, I tried both multiple column order by using Mysql, but I am not getting correct response. Can anyone help in this., I want to above order in MySQL,
Well, what this query does is to sort it in descending order by is_premium and then displays it simply that way
SELECT * FROM CLIENTE ORDER BY `tid`='V001' DESC, `is_premium` DESC;
Note : Where it says table put your table
I put a link with the test code for you to try it. : https://www.db-fiddle.com/f/3PnzHErrf2fZFGZY67K12X/57
Probably, #Chinnu the most efficient way to do what you need is get all from your DB and do some logic in your backend instead use mysql-query. Once you have an object with everything, you can apply conditions that will make sure if some patient is already in the queue and if that patient is premium or not and so on.
(SELECT * FROM PATIENTS WHERE `is_serial` = 0 LIMIT 1)
UNION
(SELECT * FROM PATIENTS ORDER BY `is_serial` = 0 DESC, `is_premium` DESC LIMIT 0, 1000);
Test here: https://www.db-fiddle.com/f/3PnzHErrf2fZFGZY67K12X/93
Picture with is_premium=1 first
Picture with is_premium=0 first
That should resolve your problem but it will put all is_premium = 1 before the others keeping the first row intact.
For patients with checkup completed too.
If you want to select only unchecked patients:
(SELECT * FROM PATIENTS WHERE `is_serial` = 0 LIMIT 1)
UNION
(SELECT * FROM PATIENTS WHERE `is_serial` = 0 ORDER BY `is_premium` DESC LIMIT 0, 1000);

How to first get a specific row by id and after order the rest alphabetically by specific column

I am trying to get a specific id (53) to be first in order when retrieving my data and after that order title alphabetically. I found some answers here but none were what I am looking for.
Currently this is my query:
SELECT *
FROM snm_categories
WHERE parent_id = ".$conn->real_escape_string($getcat['id'])."
AND published = 1
ORDER BY CASE WHEN id = 53 THEN 0 ELSE 1 END, id, title
This correctly shows the first result with id 53 but the remaining items are not ordered alphabetically by title. How can I do that?
ORDER BY CASE WHEN id = 53 THEN 0 ELSE 1 END, title, id,
You have to change the sequence of the fields. You write the title column first before the id column. It matters.
MySQL treats boolean values as numbers, with "1" for true and "0" for false.
So, you can simplify the logic to:
ORDER BY (id = 53) DESC, title, id

Order by date and field

I have SELECT query with LEFT JOINT (SELECT) and order by COALESCE(SELECT2.date, SELECT1.date) but i need to order it too with important field.
So: if row have important = 1 it need to be first, then important = 0 but ordered by coleasce date so as so. Is this even posible?
You could place the important column first in the order by list. Sorting desc (for descending) will place 1 before 0:
order by
important DESC
, coalesce(select2.date, select1.date)
You can even use case to sort the important column in a custom way:
order by
case
when important = 'SENATOR' then 1
when important = 'PATRICIAN' then 2
when important = 'PLEBS' then 3
else 4
end
, coalesce(select2.date, select1.date)

how can I tell if the last x rows of 'state' = 1

I need help with a SQL query.
I have a table with a 'state' column. 0 means closed and 1 means opened.
Different users want to be notified after there have been x consecutive 1 events.
With an SQL query, how can I tell if the last x rows of 'state' = 1?
If, for example, you want to check if the last 5 consecutive rows have a state equals to 1, then here's you could probably do it :
SELECT IF(SUM(x.state) = 5, 1, 0) AS is_consecutive
FROM (
SELECT state
FROM table
WHERE Processor = 3
ORDER BY Status_datetime DESC
LIMIT 5
) as x
If is_consecutive = 1, then, yes, there is 5 last consecutive rows with state = 1.
Edit : As suggested in the comments, you'll have to use ORDER BY in your query, to get the last nth rows.
And for more accuracy, since you have a timestamp column, you should use Status_datetime to order the rows.
You should be able to use something like this (replace the number in the HAVING with the value of x you want to check for):
SELECT Processor, OpenCount FROM
(
SELECT TOP 10 Processor, DateTime, Sum(Status) AS OpenCount
FROM YourTable
WHERE Processor = 3
ORDER BY DateTime DESC
) HAVING OpenCount >= 10