[英]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我的表由 id、segmentID、月、年和平均速度组成,我在这里创建了一些演示数据的 sqlfiddle: 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.我需要识别上个月平均行驶速度下降超过 10% 的路段。
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这是更新的 SQLFiddle - http://sqlfiddle.com/#!2/183c1/25
here is my solution这是我的解决方案
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.关键是要跟踪上个月和下个月之间的关系,所以我正在做 year*100+month 和 after group by year and moth 检查 year*100+month 字段中的差异 1 和 89。 Also it is pitty that MySQL does not support CTE and makes query ugly using derivered tables.同样遗憾的是,MySQL 不支持 CTE,并且使用派生表使查询变得丑陋。
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 CTE 代码适用于除 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
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.