MYSQL check the value of the next row - mysql

I have a table 'mytable' like this
ID | dateTime | data |
------------------------------------------
1 | 2013-09-01 00:15:00 | some data |
2 | 2013-09-01 00:15:00 | some data |
4 | 2013-09-01 00:15:00 | some data |
5 | 2013-09-01 00:30:00 | some data |
6 | 2013-09-01 00:30:00 | some data |
7 | 2013-09-01 00:30:00 | some data |
8 | 2013-09-01 00:45:00 | some data |
9 | 2013-09-01 00:45:00 | some data |
10 | 2013-09-01 00:45:00 | some data |
I was fine before but I accidentally changed the dateTime to round to 15 minutes (I was supposed to round it for 5 minutes) please refere to this, No I want to round the time for 5 minutes.
I think the only way I can do this, is to get the dateTime of one record then check the record in the next row, if both are same then add 5 minutes into it.
How do I get the value of the next row and compare it with previous one?
Can anyone help me with this??
Thanks

This query will output the new datetime values, where I add 5 minutes every time the datetime is the same as the previous row, ordered by Id:
SELECT ID,
DATE_ADD(dateTime, INTERVAL 5 * (ID -
(SELECT MIN(ID) FROM MyTable T2 WHERE T2.dateTime = T1.dateTime)
) MINUTE) AS dateTime,
data
)
FROM MyTable T1
It works by adding 5 times the difference in ID values between the current row and the first row (minimum ID) of the same dateTime value.
While this will definitely do what you want, depending on how you rounded down to 15 minutes, the output will not necessarily be the same as if you had rounded down to 5 minutes from your original data. Your best option would be to restore from a backup.

Related

SELECT only 9:00 and 21:00 data per day, from mySQL table

I have a mySql table which receives data in every hour from a smart scale (only one scale/table), so there is 24 row each day.
The Mysql table contains 3 column:
timestamp: 2022-02-01 20:00:27 (only for example), Weight (Float), Temp(float).
I have a query to see only 21:00 data from each day:
SELECT
DATE(timestamp),
Weight as Weight21,
Temp as Temp21
FROM table_name
WHERE HOUR(timestamp) >= 21
GROUP BY DATE(timestamp)
this will show me the following:
Date | Weight21 | Temp21 |
--------------------------------------
2022-01-01 | 23,1 | 16,0 |
2022-01-02 | 24,4 | 17,5 |
2022-01-03 | 25,3 | 12,3 |
2022-01-04 | 26,2 | 10,4 |
2022-01-05 | 27,0 | 15,8 |
Now, i would like to make a query to see both 9:00 and 21:00 data from each day, but mySql don't let me to use multiple WHERE cluase or multiple SELECT. The other problem is, that it can happen, that some day have no 9:00 or 21:00 data, or both can missing. In this case would be good to write NULL or something. So i want a query to make something like this:
Date | Weight9 | Weight21 | Temp9 | Temp21 |
-----------------------------------------------------------------
2022-01-01 | 23,1 | 27,2 | 12.1 | 16.3 |
2022-01-02 | 24,3 | 28,4 | 13.6 | 15.2 |
2022-01-03 | NULL | 29,7 | NULL | 12.7 |
2022-01-04 | 26,5 | 30,3 | 12.1 | 14.3 |
2022-01-05 | 27,7 | 31,6 | 11.0 | 16.4 |
For you first question correct statement you want to use is 'OR' and not another 'WHERE'.
If you want to see booth results from 9:00 and 21:00 your WHERE should be like this:
WHERE HOUR(timestamp) = 21 OR HOUR(timestamp) = 9
Now to your second question i'm afraid you can't do it with just one table that store your data. My best way to do this is in your backend to send this date/day as null.
I think this should cover your requirements:
SELECT
DATE(timestamp),
MAX(CASE WHEN HOUR(timestamp)=9 THEN Weight END) as Weight9,
MAX(CASE WHEN HOUR(timestamp)=21 THEN Weight END) as Weight21,
MAX(CASE WHEN HOUR(timestamp)=9 THEN Temp END) as Temp9,
MAX(CASE WHEN HOUR(timestamp)=21 THEN Temp END) as Temp21
FROM table_name
WHERE HOUR(timestamp) IN (9,21)
GROUP BY DATE(timestamp);
You can do WHERE HOUR(timestamp) IN (9,21) or WHERE HOUR(timestamp)=9 OR HOUR(timestamp)=21 but with the query above, you might not need it at all. Unless the data is too big. Also, this is using existing date data therefore any date/time not present is the data will not be returned. If you want all running dates returned as well, you need to do a LEFT JOIN with a generated date/ or calendar table - if you have one; which I do recommend you create for your own use especially when you're using older MySQL version.
See other variations in this demo fiddle

Check free time beetween times and dates with sql

Assuming that I have a table like this:
+----+----------------+------------+------------+-----------+----------+
| id | time_needed | date_start | date_stop | hour_start| hour_stop |
+----+----------------+------------+------------+-----------+----------+
| 1 | 30 | 2018-08-06 | 2018-08-06 | 08:00:00 | 08:30:00 |
| 2 | 96 | 2018-08-06 | 2018-08-06 | 10:45:00 | 14:21:00 |
| 3 | 20 | NULL | NULL | NULL | NULL |
| 4 | 56 | NULL | NULL | NULL | NULL |
+----+----------------+------------+------------+-----------+----------+
I know when I'll execute the operations 1 and 2, But instead for the 3 and 4 I just know the the time spent to execute the operations (20 and 56 minutes)
How can I check with mysql when I can execute the operation 3? I mean, is there a possibility to check when I have free time and for how long?
Looking at the table I can say that I have free time from the 08:31 to 10:44, but there is a way to check it with mysql?
EDIT
I would like to see the time free, beetween 8 am and 18 pm.
What you are demanding is not (all alone) a task of mysql. mysql can give you the DATA according to your query - but your programming language should add the logic of scheduling entries, whenever possible.
At first i would start with the following database changes:
Combine the date / hour columns into a datetime column.
remove the end_date / end_hour - you always can calcluate this with date_start + time_needed
So, you end up with a datatable like this:
+----+----------------+---------------------+
| id | time_needed | date_start |
+----+----------------+---------------------+
| 1 | 30 | 2018-08-06 08:00:00 |
| 2 | 96 | 2018-08-06 14:21:00 |
+----+----------------+---------------------+
Now, all you need to do is: Join the table with itself, and make sure everything is calculated as it should be:
-- new Task takes 25 Minutes.
SELECT DISTINCT L.* FROM time_table L LEFT JOIN time_table R
-- compare with every later schedule
on L.date_start < R.date_start
WHERE
-- use only rows that have enough time for the task that should be scheduled
(date_add(L.date_start, INTERVAL L.time_needed + 25 MINUTE ) < R.date_start
-- and only in the future
and date_add(L.date_start, INTERVAL L.time_needed MINUTE) > NOW()
-- due to the join, it might happen that we ignore entries in between.
-- make sure, there is no other task in the calculated timespan!
and not exists
(SELECT id FROM time_table x WHERE
x.date_start > L.date_start AND
x.date_Start < date_add(L.date_start, INTERVAL L.time_needed + 25 MINUTE) )
)
-- and ofc. the last row in the schedule.
OR isnull (R.date_start);
This returns both datarows, as 25 minutes can be scheduled right after every other task.
http://sqlfiddle.com/#!9/02020d8/1
14:21 - 08:00 is 6:21, and 30 minutes are "booked". So the gap is 5:51 - so a 350 Minute Task should fit after 08:00 - a 351 Minute Task not:
350 minutes to be scheduled:
http://sqlfiddle.com/#!9/02020d8/2
351 minutes to be scheduled:
http://sqlfiddle.com/#!9/02020d8/3
All you got to do afterwards:
Take the smalles id, and insert your schedule right after it. Remember, date_start will be prior_date_start + prior_time_needed.
See this example as well: Scheduling a 20 minute Task would have 3 options with the example data (Added 2 columns for your convenience):
http://sqlfiddle.com/#!9/02020d8/8

Obtaining max values for each day in the past 28 days

I've seen some of the past posts where there were questions about extracting max values for each day. Based on this, I tried SELECT ts, MAX(current) FROM mytable WHERE ts > date_add(now(), interval -28 day); but I only got one row back which is not what I want.
In this table, ts is my timestamp and current is another column of values. I want to get the max current values for each day in the past 28 days. However, my current values are recorded into the table every 30 mins each day. Therefore, there are many ts values for each day. Could this be the reason why the above query design doesnt work? If so, how can I amend it?
Here is an example of how my table look like for a few rows:
+---------------------+--------------+
| ts | current |
+---------------------+--------------+
| 2018-01-20 16:27:10 | 439.37 |
| 2018-01-20 17:00:18 | 378.07 |
| 2018-01-20 17:30:15 | 204.80 |
| 2018-01-20 18:00:16 | 196.50 |
| 2018-01-20 18:30:16 | 179.40 |
| 2018-01-20 19:00:16 | 183.00 |
| 2018-01-20 19:30:16 | 105.00 |

SQL - select x entries within a timespan

I'm creating a database (in MySQL) with a table of measurements. For each measurement I want to store the DateTime it came in. For showing plots within an app for different intervals (measurements of the day/week/month/year) I want sample the data points I have, so I can return e. g. 30 data points for the whole year as well as for the day/hour. This is the same as done with stock price graphs:
stock price plot for 1 day
vs
stock price plot for 1 month
As you can see, the amount of data points is the same in both pictures.
So how can I select x entries within a timespan in MySQL via SQL?
My data looks like this:
+====+====================+=============+==========+
| id | datetime | temperature | humidity |
+====+====================+=============+==========+
| 1 | 1-15-2016 00:30:00 | 20 | 40 |
+----+--------------------+-------------+----------+
| 2 | 1-15-2016 00:35:00 | 19 | 41 |
+----+--------------------+-------------+----------+
| 3 | 1-15-2016 00:40:00 | 20 | 40 |
+----+--------------------+-------------+----------+
| 4 | 1-15-2016 00:45:00 | 20 | 42 |
+----+--------------------+-------------+----------+
| 5 | 1-15-2016 00:50:00 | 21 | 42 |
+----+--------------------+-------------+----------+
| 6 | 1-15-2016 00:55:00 | 20 | 43 |
+----+--------------------+-------------+----------+
| 7 | 1-15-2016 01:00:00 | 21 | 43 |
+====+====================+=============+==========+
Let's say, I always want two data points (in reality a lot more). So for the last half hour I want the database to return data point 1 and 4, for the last ten minutes I want it to return 6 and 7.
Thanks for helping!
PS: I'm sorry for any errors in my English
OK, assuming a very simple systematic approach, you can get the first and last entry for any defined period:
select *
from table
where mydatetime =
(select
max(mydatetime)
from table
where mydatetime between '2017-03-01' and '2017-03-15'
)
OR mydatetime =
(select
min(mydatetime)
from table
where mydatetime between '2017-03-01' and '2017-03-15'
)
I believe your answer can be found at the following location:
https://stackoverflow.com/a/1891796/7176046
If you are looking to filter out any items not within your date/time your query would use:
Select * from table where Date/Time is (What you want to sort by)

Mysql timestampdiff sum between overlapped intervals

I have the following table structure:
+----+---------------------+---------------------+
| id | created_at | closed |
+----+---------------------+---------------------+
| 1 | 2017-04-03 04:00:00 | 2017-04-03 04:30:00 |
| 2 | 2017-04-03 04:25:00 | 2017-04-03 04:35:00 |
+----+---------------------+---------------------+
In my real SQL query I use timestampdiff to clacualte the diffirence between two dates in timestap field. There is no problem if the ctreated_at and closed_at of all records start in diffirent time intervals, so I would able to get time consumed for all rows as follows:
SELECT SUM(timestampdiff(SECOND, created_at, closed_at)) as TotalTime FROM table
My problem is like the shown table above, the time interval crossing. The above query will result 900 but it I should have 600
I have tried something like:
SELECT timestampdiff(
MINUTE,
a.created_at,
(SELECT max(b.closed) from times as b WHERE b.created_at < a.closed)
) as periods
FROM `times` as a
The result is:
+---------+
| periods |
+---------+
| 35 |
| 10 |
+---------+
Here I want only the first result whuch represnts the net time of the overlapped periods. Using MAX with the previous query should returns the first record but it will lead to neglect any other periods groups added in the futere supposed the table becomes:
+----+---------------------+---------------------+
| id | created_at | closed |
+----+---------------------+---------------------+
| 1 | 2017-04-03 04:00:00 | 2017-04-03 04:30:00 |
| 2 | 2017-04-03 04:25:00 | 2017-04-03 04:35:00 |
| 3 | 2017-04-03 05:00:00 | 2017-04-03 05:15:00 |
+----+---------------------+---------------------+
the above query returns:
+---------+
| periods |
+---------+
| 35 |
| 10 |
| 15 |
+---------+
Again here I don't want the second record because it describes its period which is previously counted in the first record. Indeed I don't know does it possible in MySQL to get (for the example above) only two records or even three records but the second is null, 0, negative value, etc to be distinguished among other really values.
You need to do group by the time on hourly basis and the take difference time for of max.
SELECT max(timestampdiff(
MINUTE,
a.created_at,closed) as periods
FROM `times` as a group by hour(created_at)
Now you will get result as per ur requirement.