我有下表,每次有一辆车装满油箱时都会给我看。它返回日期,车辆ID,当时的里程数和填充的升数:
| Date | Vehicle_ID | Mileage | Liters |
| 2016-10-20 | 234 | 123456 | 100 |
| 2016-10-20 | 345 | 458456 | 215 |
| 2016-10-20 | 323 | 756456 | 265 |
| 2016-10-25 | 234 | 123800 | 32 |
| 2016-10-26 | 345 | 459000 | 15 |
| 2016-10-26 | 323 | 756796 | 46 |
这个想法是按月计算平均消费量(我不能白天做,因为不是每辆车每天都装满油箱。)
为此,我试图按月获得最大(里程)-min(里程)/总和(升)组。但这仅适用于1辆特定车型和1个特定月份。
如果我试用1辆特定车和几个月,最大值和最小值将无法正常返回。如果我添加所有的汽车,更糟糕的是,因为它将假设最大值和最小值,就好像每辆车都是相同的。
select convert(char(7), Date, 127) as year_month,
sum("Liters tanked")/(max("Mileage")-min("Mileage"))*100 as Litres_per_100KM
from Tanking
where convert(varchar(10),"Date",23) >= DATEADD(mm, -5, GETDATE())
group by convert(char(7), Date, 127)
这不会起作用,因为它将假设所有车辆的最大值和最小值。
“工作流程”应该是这样的: - 每个月,获得每辆车的最大和最小里程。计算max-min以获得当月骑行的里程数。将每辆车的里程数相加,得到所有车辆的总里程数。将升数加起来。将总升数除以总里程数。
我如何得到结果:
| YearMonth | Average |
| 2016-06 | 30 |
| 2016-07 | 32 |
| 2016-08 | 46 |
| 2016-09 | 34 |
答案 0 :(得分:1)
这是一个比看起来更复杂的问题。问题是你不想在几个月之间失去里程。做这样的事很有诱惑力:
select year(date), month(date),
sum(liters) / (max(mileage) - min(mileage))
from Tanking
where Date >= dateadd(month, -5, getdate())
group by year(date), month(date);
但是,这会错过跨越月边界的英里和升。此外,本月第一个记录的升数是之前的 milage差异。哎呀!这是不正确的。
解决此问题的一种方法是查找下一个值。查询看起来像这样:
select year(date), month(date),
sum(next_liters) / (max(next_mileage) - min(mileage))
from (select t.*,
lead(date) over (partition by vehicle_id order by date) as next_date,
lead(mileage) over (partition by vehicle_id order by date) as next_mileage,
lead(liters) over (partition by vehicle_id order by date) as next_liters
from Tanking t
) t
where Date >= dateadd(month, -5, getdate())
group by year(date), month(date);
这些查询使用简化的列名,因此转义字符不会干扰逻辑。
编辑:
哦,你有多辆车(可能是vehicle_Id
所在的)。您需要两个级别的聚合。第一个查询看起来像:
select yyyy, mm, sum(liters) as liters, sum(mileage_diff) as mileage_diff,
sum(mileage_diff) / sum(liters) as mileage_per_liter
from (select vehicle_id, year(date) as yyyy, month(date) as mm,
sum(liters) as liters,
(max(mileage) - min(mileage)) as mileage_diff
from Tanking
where Date >= dateadd(month, -5, getdate())
group by vehicle_year(date), month(date)
) t
group by yyyy, mm;
第二个查询的类似更改(vehicle_id
子句中的partition by
)适用于第二个版本。
答案 1 :(得分:0)
尝试在子查询中获取每辆车每月的总和。然后使用子查询的值计算外部查询中的每月平均值:
select year_month,
(1.0*sum(liters_per_car)/sum(mileage_per_car))*100.0 as Litres_per_100KM
from (
select convert(char(7), [Date], 127) as year_month,
sum(Liters) as liters_per_car,
max(Mileage)-min(Mileage) as mileage_per_car
from Tanking
group by convert(char(7), [Date], 127), Vehicle_ID) as t
group by year_month
答案 2 :(得分:0)
您可以使用CTE获得dif(里程),然后计算消耗量:
可在此处查看:http://rextester.com/OKZO55169
with cte (car, datec, difm, liters)
as
(
select
car,
datec,
mileage - lag(mileage,1,mileage) over(partition by car order by car, mileage) as difm,
liters
from #consum
)
select
car,
year(datec) as [year],
month(datec) as [month],
((cast(sum(liters) as float)/cast(sum(difm) as float)) * 100.0) as [l_100km]
from
cte
group by
car, year(datec), month(datec)