I have a table that looks like this and i want to know the number of entries that are registered over a six hour time period and display that period which has max number of entries.
Time
09:42:29
10:37:28
15:18:49
15:28:34
16:43:51
18:14:10
18:26:06
18:26:14
So for each element in Time column, i will include a 6 hour period starting from that element and count how many entries in that column will fall in that period.
Ex 09:42:29 will have the end period has 15:42:29 and it should have count as 4 (09:42:29,10:37:28
15:18:49,15:28:34).
So do this for each element in Time Column and whichever element has max count, that will be the starting time of the period and display the start and end period accordingly.
Help me with writing a mysql query for this. Thank You!!!
Hope it helps
select
T.TimeStart,
T.TimeEnd,
COUNT(*)
from (
select
T.Time TimeStart,
date_add(T.Time,INTERVAL 6 HOUR) TimeEnd
from TimeTable T
) T
inner join TimeTable T2 on
T2.Time between T.TimeStart and T.TimeEnd
group by
T.TimeStart,
T.TimeEnd
The code below is for MSSQL but it works as expected and should give you some guidelines how the example above could be used
WITH TimeTable([Time]) AS (
select
CONVERT(DATETIME,a.a)
from (
values
('09:42:29'),
('10:37:28'),
('15:18:49'),
('15:28:34'),
('16:43:51'),
('18:14:10'),
('18:26:06'),
('18:26:14'))a(a)
)
select
convert(time(7),T.TimeStart)TimeStart,
convert(time(7),T.TimeEnd)TimeEnd,
COUNT(*) [Ocorrences]
from (
select
T.Time TimeStart,
DATEADD(HOUR,6,T.Time) TimeEnd
from TimeTable T
) T
inner join TimeTable T2 on
T2.Time between T.TimeStart and T.TimeEnd
group by
T.TimeStart,
T.TimeEnd
Related
I have a quey which has growth rates over a period of time. I am trying to obtain the overall growth between two rows that I specify. Here is the SQL fiddle http://sqlfiddle.com/#!9/1756ca/2
select i1.Month, i1.Rate, EXP(SUM(LOG(1+i2.Rate))) InfRate
from Inflation i1
inner join Inflation i2 on i1.Month >=i2.Month
group by i1.Month, i1.Rate
order by Month DESC
This seems to work correctly and I am able to get the growth rate for the entire Month range in the fiddle, however I am trying to use a derived table so that I can specify the Month period, like this, however it is not working
select i1.Month, i1.Rate, EXP(SUM(LOG(1+i2.Rate))) InfRate
from (SELECT * FROM `Inflation` WHERE Month between '2020-01-01' and '2022-01-01') as DT
inner join Inflation i2 on i1.Month >=i2.Month
group by i1.Month, i1.Rate
order by Month DESC
I get the error #1054 - Unknown column 'i1.Month' in 'field list'
I am trying to use a derived table for the period between '2020-01-01' and '2022-01-01' or any other range that I specify, however it does not seem to be working for me. Any help will be appreciated.
The expected result is something like this, considering that only the period between '2020-01-01' and '2022-01-01' was queried
http://sqlfiddle.com/#!9/13f818/1
There seems to be some problem with the fiddle, here is an updated one
https://dbfiddle.uk/TwQ7VWs2
If you are looking for "inflation since the start of 2020, you need to limit i2:
Select DT.Month, DT.Rate, EXP(SUM(LOG(1+i2.Rate))) InfRate
from (SELECT * FROM `Inflation` WHERE Month between '2020-01-01' and '2022-06-01') as DT
inner join Inflation i2 on DT.Month >=i2.Month
where i2.Month >= '2020-01-01' -- I added this
group by DT.Month, DT.Rate
order by Month DESC;
You don't have a table named i1 in your second example, yet you're querying values from it. I believe what you want is something like
select DT.Month, DT.Rate, EXP(SUM(LOG(1+i2.Rate))) InfRate
from (SELECT * FROM `Inflation` WHERE Month between '2020-01-01' and '2022-01-01') as DT
inner join Inflation i2 on DT.Month >=i2.Month
group by DT.Month, DT.Rate
order by Month DESC
Which replaces your i1 references with DT.
i have a table that looks like this :
what i need is For each day show the accumulated (moving) number of new Droppers in the last 5 days inclusive
Split to US vs. Non-US geos.
Report Columns:
DataTimstamp - upper boundary of a 5-day time frame
Total - number of New Droppers within the time frame
Region_US - number of New Droppers where country =’US’
Region_rest - number of New Droppers where country<>’US’
this is my code :
Create view new_droppers_per_date as Select date,country,count(dropperid) as num_new_customers
From(
Select dropper id,country,min(cast( LoginTimestamp as date)) as date
From droppers) as t1 group by date,country
Select DataTimstamp,region_us,region_rest from(
(Select date as DataTimstamp ,sum(num_new_customers) over(oreder by date range between 5
preceding and 1 preceding) as total
From new_droppers_per_date ) as t1 inner join
(Select date ,sum(num_new_customers) over(oreder by date range between 5 preceding and preceding)
as region_us
From new_droppers_per_date where country=”us”) as t2 on t1.date=t2.date inner join
(Select date, sum(num_new_customers) over(oreder by date range between 5 preceding and 1
preceding)
as region_rest
From new_droppers_per_date where country <>”us”) as t3 on t2.date=t3.date)
i was wondering if there is any easier\smarter way to do so without using so many joins and view
thank you for the help:)
Here is one way to do it using window functions. First assign a flag to the first login of each DropperId, then aggregate by day and count the number of new logins. Finally, make a window sum() with a range frame that spans over the last 5 days.
select
LoginDay,
sum(CntNewDroppers) over(
order by LoginDay
range between interval 5 day preceding and current row
) RunningCntNewDroppers
from
select
date(LoginTimestamp) LoginDay,
sum(rn = 1) CntNewDroppers
from (
select
LoginTimestamp,
row_number() over(partition by DropperId order by LoginTimestamp) rn
from mytable
) t
) t
I have a query that give me a table like this:
Person | Date_IN | Date_OUT | Structure
During a year a person ENTER and EXIT many times, ENTER and EXIT could be also the same day.
I'd like to count, for a specific day of year, how many person were IN each structure.
The final goal is to have, for a given period (1st march --> 31st march), the sum of total person for each day for each structure.
I believe the following would work. It assumes that you have a table of dates (consists of one column which contains all the dates between 1950 and 2050) and you simply join it with the person check in/out table:
SELECT dates.date, Structure, COUNT(DISTINCT Person) Persons_on_That_Date
FROM dates
LEFT JOIN turndata ON dates.date BETWEEN Date_IN AND Date_OUT
WHERE dates.date BETWEEN '2018-03-01' AND '2018-03-31'
GROUP BY dates.date, Structure
ORDER BY Structure, dates.date
Demo Here
Note: the above assumes that the out date is inclusive (the person is counted as inside on that date). If out date is exclusive then the ON clause becomes:
... ON Date_IN <= dates.date AND dates.date < Date_OUT
Please use below query, data is grouped by structure for particular timeframe.
SELECT structure, COUNT(DISTINCT person) as no_of_person
FROM table_name
WHERE DATE(Date_IN) BETWEEN '2018-08-01' AND '2018-08-31'
GROUP BY structure
You say there can be no multiple date_in for the same day and person, because a person is in at least one day. So for a given date we only must look at the latest event per person until then to see whether the person is/was in that day.
These are the steps:
create a data set for the requiered days on-the-fly
join with the table and get the last date_in until that day per person
join with the table again to get the last records
aggregate per day and count persons present
This is:
select
data.day
sum(t.date_in is not null and (t.date_out is null or t.date_out = data.day)) as count_in
from
(
select days.day, t.person, max(t.date_in) as max_date_in
from (select date '2018-03-01' as day union all ...) days
left join t on t.date_in <= days.day
group by days.day, t.person
) data
left join t on t.person = data.person and t.date_in = data.max_date_in
group by data.day
order by data.day;
I have a table representing a car traveling a route, broken up into segments:
CREATE TABLE travels (
id int auto_increment primary key,
segmentID int,
month int,
year int,
avgSpeed int
);
-- sample data
INSERT INTO travels (segmentID, month, year, avgSpeed)
VALUES
(15,1,2014,80),
(15,1,2014,84),
(15,1,2014,82),
(15,2,2014,70),
(15,2,2014,68),
(15,2,2014,66);
The above schema and sample data is also available as a fiddle.
What query will identify segment IDs where average driving speed decreased by more than 10% compared to the previous month?
here is my solution
Sqlfidle demo
The key is to keep track between previous month and next so i`m doing year*100+month and after group by year and moth check for difference 1 and 89 in year*100+month field.
Also it is pitty that MySQL does not support CTE and makes query ugly using derivered tables.
Code:
select s.month,s.speed,m.month as prevmonth,m.speed as sp, 100-s.speed/m.speed*100 as speeddiff from
(SELECT segmentid,month,year*100+month as mark,avg(avgSpeed) as speed from travels
group by segmentid,month,year*100+month
) as s
,
(SELECT segmentid,month,year*100+month as mark,avg(avgSpeed) as speed from travels
group by segmentid,month,year*100+month
) as m
where s.segmentid=m.segmentid and (s.mark=m.mark+1 or s.mark=m.mark+89) and (m.speed-(m.speed/10))>s.speed;
CTE code working on every DB except MySQL
with t as(SELECT segmentid,month,year*100+month as mark,avg(avgSpeed) as speed from travels
group by segmentid,month,year*100+month
)
select s.month,s.speed,m.month as prevmonth,m.speed as sp, 100-s.speed/m.speed*100 as speeddiff from t s
inner join t m on s.segmentid=m.segmentid and (s.mark=m.mark+1 or s.mark=m.mark+89)
where (m.speed-(m.speed/10))>s.speed;
You need to select each month, join the next month (which is a little convoluted due to your table structure) and find the decrease(/increase). Try the following complex query
SELECT
t1.segmentID, t1.month, t1.year, AVG(t1.avgSpeed) as avgSpeed1,
AVG(t2.avgSpeed) as avgSpeed2,
1-(AVG(t1.avgSpeed)/AVG(t2.avgSpeed)) as decrease
FROM
travels t1
LEFT JOIN
travels t2
ON
CONCAT(t2.year,'-',LPAD(t2.month,2,'00'),'-',LPAD(1,2,'00')) = DATE_ADD(CONCAT(t1.year,'-',LPAD(t1.month,2,'00'),'-',LPAD(1,2,'00')), INTERVAL -1 MONTH)
GROUP BY
segmentID, month, year
HAVING
avgSpeed1/avgSpeed2 < .9
Here is the updated SQLFiddle - http://sqlfiddle.com/#!2/183c1/25
This requires a self join. This answer will get you started. You can work on the details.
select somefields
from yourtable t1 join yourtable t2 on t1.something = t2.something
where t1.month = whatever
and t2.month = t1.month + 1
and t2.speed <= t1.speed * .9
I have a mysql database with vehicles records. I need a fast query that will return the newest records of those records that were updated within the last 4 minutes. For example vehicle "A" may be updated several times a minute so it will appear many times within the last 4min. Same with vehicle B C etc. I need only the most recent entries for each vehicle within a 4 min window. I have tried like this
SELECT *
FROM yourtable AS a
WHERE a.ts =
(SELECT MAX(ts)
FROM yourtable AS b
WHERE b.ts > NOW() - INTERVAL 5 MINUTE
AND b.name = a.name)
but it takes too long to produce results >10seconds.
You don't need the self-join.
select max(ts), name from Table1
where ts > NOW() - INTERVAL 5 MINUTE
group by name
To get all the rows for the latest updates and not only the name and timestamp:
SELECT t.*
FROM
TableX AS t
JOIN
( SELECT name
, MAX(ts) AS maxts
FROM TableX
WHERE ts > NOW() - INTERVAL 4 MINUTE
GROUP BY name
) AS grp
ON grp.name = t.name
AND grp.maxts = t.ts
You'll need at least an index on the timestamp column for this query.