2016-11-28 3 views
3

У меня есть следующая таблица, которая показывает мне каждый раз, когда автомобиль наполняется танком. Она возвращает дату, автомобиль идентификатор, пробег это было в то время и литры заполнены:Макс и Мин группы на 2 колонки

| 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  | 

Идея заключается в том, чтобы вычислить среднее Потребляемый за месяц (я не могу сделать это днем, потому что не каждый автомобиль заполняет резервуар каждый день).

Чтобы получить это, я попытался получить максимальную (пробег) -мин (пробег)/сумму (литров) по месяцам. Но это будет работать только на 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

«Я не могу сделать это днем, потому что не каждый автомобиль заливок танк каждый день ». Не является ли ежедневное потребление только ежемесячным потреблением, деленным примерно на 30? – Strawberry

+0

Привет клубника. Нет. Если бы я хотел «средний день», это сработало бы так. Но каждый день я имел в виду «день 1 - среднее значение X», «День 2 - среднее значение Y» и т. Д. –

+0

Выход включает строки для '2016-09',' 2016-08', '2016-07' и '2016-06'. Но образцы данных не содержат записей за эти месяцы. Можете ли вы обновить, чтобы мы работали против. –

ответ

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); 

Эти запросы используют упрощенные имена столбцов, поэтому escape-символы не мешают логике.

EDIT:

О, у вас есть несколько машин (вероятно, что 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 пунктах) будет работать на вторую версию.

+0

спасибо за ответ. Если мы хотим приблизиться (так как невозможно понять пробег и литеры, которые охватывают месяцы). Первый запрос не сработает, потому что предположим, что есть 30 автомобилей. Максимальный пробег может быть от автомобиля 1, который имеет 500 км миль на одометре, а мин может быть от автомобиля 21, который имеет 10 миль. Даже если каждый автомобиль проехал всего 10 миль в этом месяце, общий пробег должен составлять 300 миль. Но max (пробег) -min (пробег) вернет 500k - 10miles. Это моя проблема. Как я могу получить разницу между max и min для каждого автомобиля, а затем суммировать их. –

+0

Спасибо, помощник! Это работает! –

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 
0

Вы можете использовать CTE, чтобы получить диф (пробег), а затем рассчитать расход:

Может проверить его здесь: 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) 
+0

спасибо товарищу! это тоже работает! –