SQL Query to group and add time between consecutive rows - mysql

Need help with SQL Query (MySQL)
Say I have a table with data as..
The table has the Latitude and Longitude locations logged for a person at some time intervals (TIME column), And DISTANCE_TRAVELLED column has the distance traveled from its previous record.
If i want to know how many minutes a person was not moving (i.e DISTANCE_TRAVEKLLED <= 0.001)
what query should i use?
Can we also group the data by Date? Basically i want to know how many minutes the person was idle in a specific day.

You need to get the previous time for each record. I like to do this using a correlated subquery:
select t.*,
(select t2.time
from table t2
where t2.device = t.device and t2.time < t.time
order by time desc
limit 1
) as prevtime
from table t;
Now you can get the number of minutes not moved, as something like:
select t.*, TIMESTAMPDIFF(MINUTE, prevftime, time) as minutes
from (select t.*,
(select t2.time
from table t2
where t2.device = t.device and t2.time < t.time
order by time desc
limit 1
) as prevtime
from table t
) t
The rest of what you request is just adding the appropriate where clause or group by clause. For instance:
select device, date(time), sum(TIMESTAMPDIFF(MINUTE, prevftime, time)) as minutes
from (select t.*,
(select t2.time
from table t2
where t2.device = t.device and t2.time < t.time
order by time desc
limit 1
) as prevtime
from table t
) t
where distance_travelled <= 0.001
group by device, date(time)
EDIT:
For performance, create an index on table(device, time).

Related

Getting the last and oldest price of a grouped row

I have this query and I want to select the currentprice(the most current price sorted by time) and the oldprice(the last row sorted by time) in the same columns per row. I figured out how to select the currentprice but how can I select both in the same query?
In the end I want to make a calculation for the percentage of gain or drop with ROUND((latestprice - oldprice) / oldprice * 100, 2) as gain_ratio
WITH tmp AS (
SELECT TrackID, ID, price, MAX(Time) as maxtime, MIN(Time) as mintime
FROM track
WHERE Time > NOW() - INTERVAL 1 HOUR
GROUP BY ID
)
SELECT T.TrackID, T.ID, tmp.Price as currentprice, T.Time
FROM track AS T
JOIN tmp ON T.ID = tmp.ID
WHERE T.Time = tmp.maxtime;
I'm really struggeling to grasp how to make a CTE query, I have read the documentation several times
Have you tried to change your where clause to...?:
WHERE T.Time = tmp.maxtime or T.Time = tmp.mintime

SQL query Compare two WHERE clauses using same table

I am looking to compare two sets of data that are stored in the same table. I am sorry if this is a duplicate SO post, I have read some other posts but have not been able to implement it to solve my problem.
I am running a query to show all Athletes and times for the most recent date (2017-05-20):
SELECT `eventID`,
`location`,<BR>
`date`,
`barcode`,
`runner`,
`Gender`,
`time` FROM `TableName` WHERE `date`='2017-05-20'
I would like to compare the time achieved on the 20th May with the previous time for each athlete.
SELECT `time` FROM `TableName` WHERE `date`='2017-05-13'
How can I structure my query showing all of the ATHLETES, TIME on 13th, TIME on 20th
I have tried some methods such as UNION ALL for example
You can get the previous time using a correlated subquery:
SELECT t.*,
(SELECT t2.time
FROM TableName t2
WHERE t2.runner = t.runner AND t2.eventId = t.eventId AND
t2.date < t.date
ORDER BY t2.date DESC
LIMIT 1
) prev_time
FROM `TableName` t
WHERE t.date = '2017-05-20';
For performance, you want an index on (runner, eventid, date, time).

how to find duplicate records in a table within a predefined time period in sql

For example, i have following table
Mobile number Timestamp
123456 17-09-2015 11:30
455677 17-09-2015 12:15
123456 17-09-2015 12:25
453377 17-09-2015 13:15
If now is 11:30, I want to scan my table and find rows with the same numbers within the past 1 hour.
That's my SQL statement:
select a.number, a.time
from mytable a inner join
(select number, time
from mytable b
where time>=now()-Interval 1 hour and time<=now ()
group by number
Having count(*) > 1
) b
on a.number = b.number and a.time = b.time
I want to find duplicate rown with the same numbers happening within 1 hour. I should output the number and timestamp.
How about just using exists?
select t.*
from mytable t
where t.time >= now() - Interval 1 hour and
t.time <= now() and
exists (select 1
from mytable t2
where t2.number = t.number and
t2.time >= now() - Interval 1 hour and
t2.time <= now () and
t2.time <> t.time
);
However, I suspect that the problem with your query is the join to time. Just remove the time from the subquery and the on clause and you will get all numbers. Alternatively, use group by:
select t.number, group_concat(time)
from mytable t
where t.time >= now() - Interval 1 hour and
t.time <= now()
group by t.number
having count(*) > 1;

Reverse order for GROUP BY in MySQL

I need to select first value for every hour from my db. But I don't know how to reverse order on GROUP BY statement.
How can i rewrite my query (now it selects last value in hour)?
SELECT HOUR(`time`) as hour, mytable.*
FROM mytable
WHERE DATE(`time`) ="2015-09-12" GROUP BY HOUR(`time`) ORDER BY `time` ASC;
This query gave me expected result:
SELECT HOUR(`time`) as hour, sortedTable.* FROM
(SELECT electrolysis.* FROM electrolysis
WHERE DATE(`time`)='2015-09-12' ORDER BY `time`) as sortedTable
GROUP BY HOUR(`time`);
You can just select the MIN HOUR in sub query , try using the query:
SELECT * from mytable WHERE `time` IN (
SELECT MIN(HOUR(`time`)) as `hour`
FROM mytable
WHERE DATE(`time`) ="2015-09-12"
GROUP BY HOUR(`time`) ) ORDER BY `time` ASC;
You can do something like this:-
SELECT sub0.min_time,
mytable.*
FROM mytable
INNER JOIN
(
SELECT MIN(`time`) AS min_time
FROM mytable
GROUP BY HOUR(`time`)
) sub0
ON mytable.`time` = sub0.min_time
WHERE DATE(`time`) ="2015-09-12"
ORDER BY `time` ASC
This is using a sub query to get the smallest time in each hour. This is then joined back against your main table on this min time to get the record that has this time.
Note that there is a potential problem here if there are multiple records that share the same time as the smallest one for an hour. There are ways around this, but that will depend on your data (eg, if you have a unique id field which is always ascending with time then you could select the min id for each hour and join based on that)
You can use below query, which is more optimized just make sure that time field should be indexed.
SELECT HOUR(m.time), m.*
FROM mytable AS m
JOIN
(
SELECT MIN(`time`) AS tm
FROM mytable
WHERE `time` >= '2015-09-12 00:00:00' AND `time` <= '2015-09-12 23:59:59'
GROUP BY HOUR(`time`)
) AS a ON m.time=a.tm
GROUP BY HOUR(m.time)
ORDER BY m.time;

MySQL - How to select rows with the min(timestamp) per hour of a given date

I have a table of production readings and need to get a result set containing a row for the min(timestamp) for EACH hour.
The column layout is quite simple:
ID,TIMESTAMP,SOURCE_ID,SOURCE_VALUE
The data sample would look like:
123,'2013-03-01 06:05:24',PMPROD,12345678.99
124,'2013-03-01 06:15:17',PMPROD,88888888.99
125,'2013-03-01 06:25:24',PMPROD,33333333.33
126,'2013-03-01 06:38:14',PMPROD,44444444.44
127,'2013-03-01 07:12:04',PMPROD,55555555.55
128,'2013-03-01 10:38:14',PMPROD,44444444.44
129,'2013-03-01 10:56:14',PMPROD,22222222.22
130,'2013-03-01 15:28:02',PMPROD,66666666.66
Records are added to this table throughout the day and the source_value is already calculated, so no sum is needed.
I can't figure out how to get a row for the min(timestamp) for each hour of the current_date.
select *
from source_readings
use index(ID_And_Time)
where source_id = 'PMPROD'
and date(timestamp)=CURRENT_DATE
and timestamp =
( select min(timestamp)
from source_readings use index(ID_And_Time)
where source_id = 'PMPROD'
)
The above code, of course, gives me one record. I need one record for the min(hour(timestamp)) of the current_date.
My result set should contain the rows for IDs: 123,127,128,130. I've played with it for hours. Who can be my hero? :)
Try below:
SELECT * FROM source_readings
JOIN
(
SELECT ID, DATE_FORMAT(timestamp, '%Y-%m-%d %H') as current_hour,MIN(timestamp)
FROM source_readings
WHERE source_id = 'PMPROD'
GROUP BY current_hour
) As reading_min
ON source_readings.ID = reading_min.ID
SELECT a.*
FROM Table1 a
INNER JOIN
(
SELECT DATE(TIMESTAMP) date,
HOUR(TIMESTAMP) hour,
MIN(TIMESTAMP) min_date
FROM Table1
GROUP BY DATE(TIMESTAMP), HOUR(TIMESTAMP)
) b ON DATE(a.TIMESTAMP) = b.date AND
HOUR(a.TIMESTAMP) = b.hour AND
a.timestamp = b.min_date
SQLFiddle Demo
With window function:
WITH ranked (
SELECT *, ROW_NUMBER() OVER(PARTITION BY HOUR(timestamp) ORDER BY timestamp) rn
FROM source_readings -- original table
WHERE date(timestamp)=CURRENT_DATE AND source_id = 'PMPROD' -- your custom filter
)
SELECT * -- this will contain `rn` column. you can select only necessary columns
FROM ranked
WHERE rn=1
I haven't tested it, but the basic idea is:
1) ROW_NUMBER() OVER(PARTITION BY HOUR(timestamp) ORDER BY timestamp)
This will give each row a number, starting from 1 for each hour, increasing by timestamp. The result might look like:
|rest of columns |rn
123,'2013-03-01 06:05:24',PMPROD,12345678.99,1
124,'2013-03-01 06:15:17',PMPROD,88888888.99,2
125,'2013-03-01 06:25:24',PMPROD,33333333.33,3
126,'2013-03-01 06:38:14',PMPROD,44444444.44,4
127,'2013-03-01 07:12:04',PMPROD,55555555.55,1
128,'2013-03-01 10:38:14',PMPROD,44444444.44,1
129,'2013-03-01 10:56:14',PMPROD,22222222.22,2
130,'2013-03-01 15:28:02',PMPROD,66666666.66,1
2) Then on the main query we select only rows with rn=1, in other words, rows that has lowest timestamp in each hourly partition (1st row after sorted by timestamp in each hour).