简体   繁体   中英

SQL complicated query

EDITED:

My table consist of id, segmentID, month, year and avg speed, i've created sqlfiddle with some demo data here: http://sqlfiddle.com/#!2/183c1/1

I need to Identify segments where average driving speed has decreased by more than 10% over the last month.

Can someone help me with that? Thanks

Thanks

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

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;

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM