Select date where there is data in-between - mysql

I have todayRainSoFar column which is filled into db every minute, and i would like to find out the maximum duration of rain this month, ie when it started to rain and how long did it last.
for example it started to rain 2014-04-01 at 08:00 and it was raining without pause until 2014-04-05 10:00
i have trouble with combined queries.
// this will select rows when there was any rain this month
SELECT LogDateTime, TodayRainSoFar
FROM sibeniku_monthly
WHERE TodayRainSoFar > 0.0
AND DATE_FORMAT(LogDateTime, "%m.") = 04
now I am looking for something to count maximum duration of in-between rows (LogDateTime is datetime and range is 1 minute), smth like
AND MAX (COUNT BETWEEN rows)

The approach used below is to keep a counter of consecutive minutes of rain and then get the row which has maximum value of the counter (this would give you the maximum duration of consecutive rain). Counter will be reset to 0 if rain has ended.
SELECT DATE_SUB(LogDateTime, INTERVAL counter MINUTE) AS StartTime, LogDateTime AS EndTime FROM (
SELECT IF(TodayRainSoFar = 0, #i:=0, #i:=#i+1) AS `counter`,
LogDateTime, TodayRainSoFar
FROM
sibeniku_monthly, (SELECT #i:= 0) i
ORDER BY LogDateTime
) t
ORDER BY `counter` DESC
LIMIT 0,1
Working Demo: http://sqlfiddle.com/#!2/8578b8/8

Try using DATEDIFF in your script, here is a link: http://technet.microsoft.com/en-us/library/ms189794.aspx
This will give you everything you need to know about DATEDIFF.

Related

Query that accounts for changes in the hour of a timestamp

The problem is as follows. I have a table that contains the following columns:
machine
timestamp
speed (meters/minute)
C1
22/9/2020, 16:45
15
C1
22/9/2020, 16:55
5
C1
22/9/2020, 17:20
19
What I want to know is the distance travelled in each hour for each machine, so I need to subtract the timestamp of the current row from the timestamp of the next row, and then multiply by the speed of the first row (e.g: 16:55 - 16:45 = 10 minutes -> 10 * 15 = 150 meters between 16:45 and 16:55).
I was able to do that by using a logic similar to the one below (it is not all the same query):
' 1st get the timestamp of the next row'
lead(query."timestamp") OVER (PARTITION BY query.id ORDER BY query."timestamp") AS lead_timestamp
' 2nd get the duration'
query."lead_timestamp" - query."timestamp" AS duration
' 3rd calculate the distance'
query."duration" * query."speed" AS distance
' 4th group by hour'
GROUP BY date_trunc('hour', CAST(query."timestamp" AS timestamp)
It works almost 100% fine. I get a table similar to the one below:
machine
timestamp
duration (meters)
C1
22/9/2020, 16:00
275
C1
22/9/2020, 17:00
...
But as you can see, as I group data per hour, the total meters for the hour 16:00 are not correct because there wasn't a timestamp after the timestamp equal to "22/9/2020, 16:55" that forced the grouping to end at "22/9/2020, 16:59". So, in the end, I added to the hour 16:00 part of the duration for the hour 17:00 (those 20 minutes were added to hour 16:00).
I am not sure how to solve this problem but I have looked into UNION to add an 'artificial' row whenever there's a transition of hour between timestamps, before even starting subtracting values to calculate the duration. But it seems rather complicated since I would have to do it for each machine and I don't know how many rows it would be.
Can you help me? Thanks! If I was not clear pls ask for more info!
This could be of help:
WITH cte as (
select 'c1' as machine, '2020-09-22 16:46' as timestamp, 15 as speed
union all
select 'c1', '2020-09-22 16:56', 5
union all
select 'c1', '2020-09-22 17:20', 19)
select
machine,
timestamp,
speed,
lead(timestamp) over (partition by machine) nextTime,
TIMEDIFF( lead(timestamp) over (partition by machine), timestamp) diffTime,
minute(TIMEDIFF( lead(timestamp) over (partition by machine), timestamp))*speed meters
from cte;
output:
machine
timestamp
speed
nextTime
diffTime
meters
c1
2020-09-22 16:46
15
2020-09-22 16:56
00:10:00.000000
150
c1
2020-09-22 16:56
5
2020-09-22 17:20
00:24:00.000000
120
c1
2020-09-22 17:20
19

MySQL average value of each hour for the last 30 days

I have a table, that is updated every minute and I need to calculate the average value of each hour, for the values of the last 30 days.
Timestamp | SB1_AC_GES_DIFF
2020-07-14 15:13:04 30
2020-07-14 15:12:07 27
... ...
I want to save the results in a second table named avgTable like this
Timestamp | AVG_SB1
15:00 29
16:00 32
... ...
It would be perfect if the table could update itself once a day, maybe when it's 12 o'clock and the the date part for the day changes.
You can try:
INSERT INTO avg_table
SELECT Date_format(Timestamp, "%h:00:00") AS HourlyTimeStamp,
Avg(sb1_ac_ges_diff) AS "AVG_SB1"
FROM table
WHERE Timestamp between DATEADD(DAY, -30, GETDATE()) AND GETDATE()
GROUP BY 1
Assuming that you want the average rolling average, agnostic of the day.
You can just use the hour() function:
select hour(timestamp) as hh, avg(sb1_ac_ges_diff)
from t
group by hh;
You can convert this to a string or time if you want, but that does not seem useful to me.
If you actually want the hour for each day, then:
select date(timestamp) as dd, hour(timestamp) as hh, avg(sb1_ac_ges_diff)
from t
group by dd, hh;

MySQL: need to calculate the last Friday of a month

I'm trying to solve a task: I have a table containing information about ships' battles. Battle is made of name and date. The problem is to get the last friday of the month when the battle occurred.
WITH num(n) AS(
SELECT 0
UNION ALL
SELECT n+1 FROM num
WHERE n < 31),
dat AS (
SELECT DATEADD(dd, n, CAST(battles.date AS DATE)) AS day,
dateadd(dd, 0, cast(battles.date as date)) as fight,
name FROM num,battles)
SELECT name, fight, max(day) FROM dat WHERE DATENAME(dw, day) = 'friday'
I thought there must be a maximum of date or something, but my code is wrong.
The result should look like this:
Please, help!!
P.S. DATE_FORMAT is not available
Possible problem: as spencer7593 noticed - and as I should have done and didn't - your original query is not MySQL at all. If you're porting a query that's OK. Otherwise this answer will not be helpful, as it makes use of MySQL functions.
The day you want is number 4 (0 being Sunday in MySQL).
So you want the last day of the month if the last day of the month is a 4; if the day of the month is a 5 you want a date which is 1 day earlier; if the day of the month is a 3 you want a date which is 1 day later, but that's impossible (the month ends), so you really need a date six days earlier.
This means that if the daynumber difference is negative, you want it modulo seven.
You can then build this expression (#DATE is your date; I use a fake date for testing)
SET #DATE='2015-02-18';
DATE_SUB(LAST_DAY(#DATE), INTERVAL ((WEEKDAY(LAST_DAY(#DATE))+7-4))%7 DAY);
It takes the last day of the month (LASTDAY(#DATE)), then it computes its weekday, getting a number from 0 to 6. Adds seven to ensure positivity after subtracting; then subtract the desired daynumber, in this case 4 for Friday.
The result, modulo seven, is the difference (always positive) from the last day's daynumber to the wanted daynumber. Since DATE_SUB(date, 0) returns the argument date, we needn't use IF.
SET #DATE='1962-10-20';
SELECT DATE_SUB(LAST_DAY(#DATE), INTERVAL ((WEEKDAY(LAST_DAY(#DATE))+7-4))%7 DAY) AS friday;
+------------+
| friday |
+------------+
| 1962-10-26 |
+------------+
Your query then would become something like:
SELECT `name`, `date`,
DATE_SUB(LAST_DAY(`date`),
INTERVAL ((WEEKDAY(LAST_DAY(`date`))+7-4))%7 DAY) AS friday
FROM battles;

MySQL time diff grouped by day

I have a table from which I'm trying to extracted summed timediff information grouped by days. I don't really know if this is possible
Table columns: mode_type, start_time.
A record exists in this table for each time an employee starts or stops a timer. mode_type = 1 for start, mode_type = 0 for stop.
I'd like to return a sum of the seconds used for each day in the last 30 days.
E.g:
date, seconds_used
02/04/2014, 25
03/04/2014, 12415
04/04/2014, 925
Currently I can return a list of seconds used per mode_type and date but this required later calc in PHP.
SELECT
mode_type,
Sum(Unix_Timestamp(start_time)) AS time,
start_time
FROM
activations
WHERE
start_time < Date(Now() + INTERVAL 1 MONTH)
GROUP BY
mode_type, Day(start_time)
ORDER BY
start_time
I'm stuck... is this possible or do I need to do revert to calculating the diff in PHP post request?
Thanks in advance.
Can you try with this:
SELECT DATE(start_time) AS startdate, TIME_TO_SEC(TIMEDIFF(NOW(),start_time)) AS secs
FROM activations
GROUP BY
startdate

MySQL query: get data in specific interval

I have a MySQL Table with one datetime column. I want to prevent that the PHP-script gets to much data. So i'm searching for a solution that a MySql query only selects rows which have a distance of 1 minute or whatever. is there something simple or do i have to code a for-loop with a new mysql query every time.
Example
timestamp
2012-09-25 00:00:00-->
2012-09-25 00:00:50
2012-09-25 00:01:23
2012-09-25 00:01:30-->
2012-09-25 00:02:33
2012-09-25 00:02:40
2012-09-25 00:03:01-->i want those
thanks in advance
Try this :
SELECT create_time
FROM timeTable
WHERE create_time
IN (
SELECT min( create_time )
FROM timeTable
GROUP BY FROM_UNIXTIME( UNIX_TIMESTAMP( create_time ) - MOD( UNIX_TIMESTAMP( create_time ) , 60 ) );
How it works :
i) Groups the table by datetime rounded to the interval, 1 minute (60 seconds) here.
ii) Gets the top row from each group.
This can be a good sampling criteria for your data.
This query can be optimized alot on these points:
i) Put a where clause for a date = REQUIRED DATE, and then do other operations on hour+minutes instead of whole datetime.
ii) If your interval is 1 minute, then substring of the timestamp or date_format can be tried too to round it off to nearest minute.
eg.
SELECT create_time
FROM timeTable
WHERE create_time
IN (
SELECT min( create_time )
FROM timeTable
GROUP BY DATE_FORMAT( `create_time` , 'Y-M-D %H:%i' )
);
Try this
SET #time := '1000-01-01 00:00:00';
SET #interval := 60;
SELECT colDate
FROM table
WHERE TIMESTAMPDIFF( SECOND, #time, colDate ) >= #interval
AND #time := colDate
How it works.
#interval is the time difference desired between the current and previous colDate. The first parameter in TIMESTAMPDIFF determines the unit of time that the interval will use. ex: SECOND, MINUTE, HOUR, DAY, WEEK, MONTH, QUARTER, or YEAR.
#time keeps track of the previous colDate, and it is compared with the current row. If the difference between the previous and current colDate is equal to or greater than the interval, it is included.
WHERE timestamp LIKE '%:30:00%' will get you every 30 seconds..
But this will only work if you have uniform entries..if your timestamps dont all end evenly.. you'll need to let us know.
EDIT
I think you may be looking for this:
How do you select every n-th row from mysql