How to get time value of MAX(speed) in MySQL? - mysql

I have a table with the following structure:
Id | Speed | Time
I want to get the time of the row that contains the maximum speed.
My example query doesn't return the correct record.
SELECT MAX(speed), time FROM info WHERE id = 1 AND time > 1234

You could order the result and take the first record:
SELECT speed, time
FROM info
WHERE id = 1 AND time > 1234
ORDER BY speed DESC
LIMIT 1

SELECT MAX(speed) as speed, time FROM info WHERE id = 1 AND time > 1234 ORDER BY id
Probably you try to get the column bad in the fetch. So try giving an alias an using it as the column name.
Or try it as getting max as a condition value in a subquery:
SELECT * FROM info WHERE id = 1 AND speed = (SELECT MAX(speed) FROM info) AND time>1234;

select id, speed, time
from info
where speed = (select max(speed)
from info);

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);

Selecting rows until a column value isn't the same

SELECT product.productID
, product.Name
, product.date
, product.status
FROM product
INNER JOIN shelf ON product.sheldID=shelf.shelfID
WHERE product.weekID = $ID
AND product.date < '$day'
OR (product.date = '$day' AND shelf.expire <= '$time' )
ORDER BY concat(product.date,shelf.expire)
I am trying to stop the SQL statement at a specific value e.g. bad.
I have tried using max-date, but am finding it hard as am making the time stamp in the query. (Combining date/time)
This example table shows that 3 results should be returned and if the status "bad" was the first result than no results should be returned. (They are ordered by date and time).
ProductID Date status
1 2017-03-27 Good
2 2017-03-27 Good
3 2017-03-26 Good
4 2017-03-25 Bad
5 2017-03-25 Good
Think I may have fixed it, I added this to my while loop.
The query gives the results in order by present to past using date and time, this while loop checks if the column of that row is equal to 'bad' if it is does something (might be able to use an array to fill it up with data). If not than the loop is broken.
I know it doesn't seem ideal but it works lol
while ($row = mysqli_fetch_assoc($result)) {
if ($row['status'] == "bad") {
$counter += 1;
}
else{
break;}
I will provide an answer just with your output as if it was just one table. It will give you the main ideia in how to solve your problem.
Basically I created a column called ord that will work as a row_number (MySql doesn't support it yet AFAIK). Then I got the minimum ord value for a bad status then I get everything from the data where ord is less than that.
select y.*
from (select ProductID, dt, status, #rw:=#rw+1 ord
from product, (select #rw:=0) a
order by dt desc) y
where y.ord < (select min(ord) ord
from (select ProductID, status, #rin:=#rin+1 ord
from product, (select #rin:=0) a
order by dt desc) x
where status = 'Bad');
Result will be:
ProductID dt status ord
-------------------------------------
1 2017-03-27 Good 1
2 2017-03-27 Good 2
3 2017-03-26 Good 3
Also tested with the use case where the Bad status is the first result, no results will be returned.
See it working here: http://sqlfiddle.com/#!9/28dda/1

MySQL Query with while loop

So, I need to make MySQL query where I select data according to time.
1| SET #t = 1490894826;
2| SELECT id
3| FROM table
4| WHERE status=1 AND
5| fav>500 AND
6| time BETWEEN #t-86400 AND #t
7| LIMIT 10
My question is, I need 10 rows from this query, but if it gives me 7 rows(for example), how can I set my query to do it again and again while number of selected rows is not 10 or time is bigger than 1480531730, and every next time #t variable needs to be substracted by 86400. Sorry for my english, take a look how I did it using PHP just to show you what I really want and I hope it will be more clearly.
$time=1490894826;
do{
$query = $db->query("SELECT * FROM table WHERE status=1 AND fav>500 AND time BETWEEN ? AND ? LIMIT 10",[$time-86400,$time]);
$time=$time-86400;
}while($query->rowCount()!=10||$time>1480531730);
Thank you
I would suggest that you do something like this:
SET #t = 1490894826;
SELECT id
FROM table
WHERE status = 1 AND fav > 500 AND
time <= #t
ORDER BY time DESC
LIMIT 10;
That is, remove the BETWEEN and just take the 10 most recent times.
Try this:
SET #t = 1490894826;
SELECT id FROM table WHERE status=1 AND fav>500 AND
time <= #t
ORDER BY time DESC LIMIT 10
This will sort by descending time, and give you the 10 most recent rows which have time <= #t. It is a very good idea to have an index on time, or (status,fav,time) to speed it up.

Checking consecutive values at a MySQL query

I have a MySQL table like this:
ID - Time - Value
And I'm getting every pair of ID, Time (grouped by ID) where Value is greater than a certain threshold. So basicaly, I'm getting every ID which has at least one time a value greater than the threshold. The query looks like this:
SELECT ID, Time FROM mydb.MYTABLE
WHERE Value>%s AND Time>=%s AND Time<=%s
GROUP BY ID
EDIT: The Time checks allow to operate in a time range of my choice between all the data which is into the table; it has nothing else to do with what I am asking.
It works perfectly, but now I want to add some filtering: I want it to avoid those times the value is greater than the threshold (let's call it alarms) if the alarm hasn't happened also the Time just before or just after. I mean: if the alarm accurs at a single, isolated instant of time instead of two consecutive instants of time, I'll consider it is a false alarm and avoid it to be returned at the query response.
Of course I can do this with a call for each Id to check for this, but I'd like to do this in a single query to make it faster. I guess I could use conditionals, but I don't have that expertise at MySQL.
Any help?
EDIT2: Example for Threshold = 10
ID - Time - Value
1 - 2004 - 9
1 - 2005 - 11
1 - 2006 - 8
2 - 2107 - 12
2 - 2109 - 13
3 - 3402 - 11
3 - 3403 - 12
In this example, only ID 3 should be a valid alarm, since 2 consecutive time values for this ID have their value > threshold. ID 1 has a single, isolated alarm, so it should be filteres. For ID 2 there are 2 alarms, but not consecutive, so it should be also filtered.
Something like this:
10 - is a threshold
0 - minimum of the time period
100000 - maximum of the time period
select ID, min(Time)
from
(
SELECT ID, Time,
(select max(time) from t
where Time<t1.Time
and Id=t1.Id
and Value>10) LAG_G,
(select max(time) from t
where Time<t1.Time
and Id=t1.Id
and Value<=10) LAG_L,
(select min(time) from t
where Time>t1.Time
and Id=t1.Id
and Value>10) LEAD_G,
(select min(time) from t
where Time>t1.Time
and Id=t1.Id
and Value<=10) LEAD_L
FROM t as t1
WHERE Value>10 AND Time>=0 AND Time<=100000
) t3
where ifnull(LAG_G,0)>ifnull(LAG_L,0)
OR
ifnull(LEAD_G,100000)<ifnull(LEAD_L,100000)
GROUP BY ID
SQLFiddle demo
This query works for searching near records.
If you need to search records by Time (+1, -1 ) as you've mentioned in the comment try this query:
select ID, min(Time) from t as t1
where Value>10
AND Time>=%s2 AND Time<=%s1
and
(
Exists(select 1 from t where Value>10
and Id=t1.Id
and Time=t1.Time-1)
OR
Exists(select 1 from t where Value>10
and Id=t1.Id
and Time=t1.Time+1)
)
group by ID
SQLFiddle demo
such alarm ?
SELECT ID, Time , count(if(value>%treshold ,1,0)) alert_active
FROM mydb.MYTABLE
WHERE Value>%s3 AND Time>=%s2 AND Time<=%s1
GROUP BY ID;
i don't understand exactly:
In this example, only ID 3 should be a valid alarm, since 2
consecutive time values for this ID have their value > threshold. ID 1
has a single, isolated alarm, so it should be filteres. For ID 2 there
are 2 alarms, but not consecutive, so it should be also filtered.
I guess that You want filter alerts:
SELECT ID, Time
FROM mydb.MYTABLE
WHERE Value>%s3 AND Time>=%s2 AND Time<=%s1
GROUP BY ID
having value<%treshold;