PostgreSQL и соответствующая строка на нескольких - PullRequest
0 голосов
/ 17 сентября 2018

Я делаю решение по статистике автомобилей, где мне нужно платить за километр пробега.

У меня есть следующая таблица:

table: cars
columns: car_id, km_driven

table: pricing
columns: from, to, price

Содержимое в моей cars таблице может быть:

car_id, km_driven
2, 430
3, 112
4, 90

Содержимое в моей таблице pricing может быть:

from, to, price
0, 100, 2
101, 200, 1
201, null, 0.5

Это означает, что первые 100 км стоят 2 долл. США за км, следующие 100 км - 1 долл. США за км, а все вышеупомянутое - 0,5 долл. США за км.

Есть ли логический и простой способ для расчета стоимости моего cars через PostgreSQL?

Так что если car управлял, напр. 201, тогда цена будет 100x2 + 100x1 + 0.5, а не просто 201x0.5.

Ответы [ 5 ]

0 голосов
/ 17 сентября 2018

Я бы написал запрос как:

select c.car_id, c.km_driven, 
   sum(( least(p.to_km, c.km_driven) - p.from_km + 1) * p.price) as dist_price
from cars c join
     pricing p
     on c.km_driven >= p.from_km
group by c.car_id, c.km_driven;

Вот дБ <> скрипка .

0 голосов
/ 17 сентября 2018

Изменено из ответа @ sean-johnston:

select 
  car_id, km_driven, 
  sum(case 
    when km_driven>=start then (least(finish,km_driven)-start+1)*price 
    else 0
  end) as dist_price
from cars,pricing
group by car_id,km_driven
  • Сохранены исходные диапазоны
  • , где km_driven> = start опущено (необязательно, но может улучшитьпроизводительность)

немного больше возиться, регистр может быть опущен, когда он находится на месте

select 
  car_id, km_driven, 
  sum((least(finish,km_driven)-start+1)*price) as dist_price
from cars,pricing
where km_driven >= start
group by car_id,km_driven

dbfiddle

0 голосов
/ 17 сентября 2018

Я бы определенно сделал бы это, используя процедуру, поскольку она может быть реализована очень простым способом с использованием циклов. Тем не менее, вы должны быть в состоянии сделать что-то похожее на это:

select car_id, sum(segment_price)
from (
  select 
  car_id, 
  km_driven, 
  f, 
  t, 
  price, 
  driven_in_segment, 
  segment_price
  from (
      select 
      car_id, 
      km_driven, 
      f, 
      t, 
      price, 
      (coalesce(least(t, km_driven), km_driven) - f) driven_in_segment, 
      price * (coalesce(least(t, km_driven), km_driven) - f) segment_price
      from 
      -- NOTE: cartesian product here
      cars, 
      pricing
      where f < km_driven
  )
) data
group by car_id
order by car_id

Я нахожу это менее читабельным, хотя.

UPDATE:

Этот запрос немного сложнее, чем необходимо, я пробовал кое-что с оконными функциями, которые в конце концов не были нужны. Здесь упрощенная версия, которая должна быть эквивалентна:

select car_id, sum(segment_price)
from (
  select 
  car_id, 
  km_driven, 
  f, 
  t, 
  price, 
  (coalesce(least(t, km_driven), km_driven) - f) driven_in_segment, 
  price * (coalesce(least(t, km_driven), km_driven) - f) segment_price
  from 
  -- NOTE: cartesian product here
  cars, 
  pricing
  where f < km_driven
) data
group by car_id
order by car_id
0 голосов
/ 17 сентября 2018

Разумное использование комбинаций «случай / сумма». Однако, во-первых, необходимо сделать ваши диапазоны согласованными. Я выберу изменить первый диапазон на 1100. Учитывая это, то следующее должно дать вам желание вы после. (Я также использовал начало / конец как от / до зарезервированные слова).

select
  car_id, km_driven,
  sum (case
    when finish is null and km_driven >= start
      then (km_driven-start+1) * price
    when km_driven >= start
      then (case
              when (km_driven - start + 1) > finish
                then (finish - start + 1)
              else (km_driven - start + 1)
              end) * price
    else 0
    end) as dist_price
from cars, pricing
where km_driven >= start
group by 1, 2;

Пояснение:

  1. Мы присоединяемся к любому диапазону, где путешествие по крайней мере до начала диапазона.
  2. Открытый диапазон обрабатывается в первом предложении case и довольно прост.
  3. Нам нужна фраза внутреннего регистра для закрытых диапазонов, поскольку нам нужна только часть пути в этом диапазоне.
  4. Затем суммируйте результаты этого для общей стоимости поездки.

Если вы не хотите (или не можете) согласовать свои диапазоны, вам нужно добавить третий внешний регистр для начального диапазона.

0 голосов
/ 17 сентября 2018

Вы можете использовать соединение и рассчитать свою стоимость, используя случай, когда

    select c.car_id, case when p.price=.5 
   then  100*2+100*1+(c.km_driven-200)*0.5 
    when   p.price=1 then 100*2+(c.km_driven-100)*1
    else c.km_driven*p.price as cost
   from cars c join pricing p
   on c.km_driven>=p.from and c.km_driven<=p.to
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...