MySQL Рассчитать минимальную стоимость услуги с разным временем запуска
Предположим, у меня есть такая таблица:
Цены
-----------------------------------------------------------
| service_id | starting_time | ending_time | price_per_hour |
-----------------------------------------------------------
| 1 | 08:00:00 | 10:00:00 | 90 |
-----------------------------------------------------------
| 1 | 10:00:00 | 11:00:00 | 50 |
-----------------------------------------------------------
| 1 | 11:00:00 | 15:00:00 | 80 |
-----------------------------------------------------------
Теперь пользователь моей веб-страницы хочет найти поставщиков услуг по самой низкой цене. Они говорят мне время начала службы, продолжительность и (здесь самая сложная часть) допуск для времени начала. Скажем, служба должна начинаться в 10 утра, должна длиться 2 часа, но они готовы прийти на час раньше или позже (+/- 1 час до времени начала).
Я не могу придумать идею одного запроса, чтобы получить минимально возможную цену, в зависимости от того, начинается ли сервис в 9, 10 или 11 утра. Время начала допуска может варьироваться. Это просто, если нет допусков, вы просто выбираете все строки из цен, которые относятся ко времени обслуживания, вычисляете их долю в цене, а затем суммируете подзапрос. Но как мне ввести переменный начальный фактор времени в это?
Это упрощенный запрос для расчета цены, зная точную отправную точку услуги. :service_start
а также service_end
заполнители.
SELECT SUM(t1.price) FROM
(SELECT price_per_hour * TIME_TO_SEC( TIMEDIFF( IF(ending_time < :service_end,
ending_time, :service_end), IF(starting_time < :service_start, :service_start,
starting_time) ) ) / 3600 AS price FROM prices WHERE service_id = 1 AND NOT
(starting_time >= :service_end OR ending_time <= :service_start)) AS t1
И теперь я понятия не имею, куда идти дальше. Как ввести изменчивость времени запуска сервиса.
РЕДАКТИРОВАТЬ:
Хорошо, я думаю, что мне было лень думать об этом раньше. Я считаю, что это не может быть сделано с помощью MySQL. Я разбил его на математические уравнения, которые могли бы его решить, и я считаю, что это не то, что вы можете реализовать в MySQL (два уравнения с большим количеством переменных). Я думаю, что для того, чтобы получить то, что я хочу, понадобятся некоторые грубые вычисления на стороне PHP.
В этом случае я хотел бы минимизировать x * 90 + y * 50 + z * 80, где x, y, z - количество часов, взятых из каждого ценового диапазона, с учетом некоторых условий, таких как x,y,z%0,5 = 0 (полчаса), x+y+z = 2 и т. Д.
РЕДАКТИРОВАТЬ 2:
Я опишу проблему более подробно, так как кажется, что не достаточно конкретен:
У меня есть три таблицы, которые имеют отношение к этой проблеме:
Сервисы
-----------------------------------------------------------------------------------------------
| service_id | service_type_id | provider_id | name | starting_time | ending_time |
-----------------------------------------------------------------------------------------------
| 2 | 1 | 3 | 2014-02-07 08:00:00 | 2014-02-07 23:00:00 |
-----------------------------------------------------------------------------------------------
цены (больше прайс-лист)
------------------------------------------------------------------------------
| service_type_id | provider_id | starting_time | ending_time | price_per_hour |
------------------------------------------------------------------------------
| 1 | 3 | 08:00:00 | 10:00:00 | 90 |
------------------------------------------------------------------------------
| 1 | 3 | 10:00:00 | 11:00:00 | 50 |
------------------------------------------------------------------------------
| 1 | 3 | 11:00:00 | 15:00:00 | 80 |
------------------------------------------------------------------------------
| 1 | 3 | 15:00:00 | 23:00:00 | 70 |
------------------------------------------------------------------------------
service_slots
-----------------------------------------------------------------------------------
| service_slot_id | service_id | starting_time | ending_time | booked |
-----------------------------------------------------------------------------------
| 1 | 2 | 2014-02-07 08:00:00 | 2014-02-07 09:00:00 | 1 |
| 2 | 2 | 2014-02-07 09:00:00 | 2014-02-07 17:00:00 | 0 |
| 3 | 2 | 2014-02-07 17:00:00 | 2014-02-07 19:00:00 | 1 |
| 4 | 2 | 2014-02-07 19:00:00 | 2014-02-07 21:00:00 | 1 |
| 5 | 2 | 2014-02-07 21:00:00 | 2014-02-07 23:00:00 | 0 |
-----------------------------------------------------------------------------------
Первая таблица содержит график обслуживания провайдера. Провайдер говорит, что предлагает услугу с 8:00 до 23:00. Вы можете забронировать столько времени от этой услуги, сколько захотите (подумайте о бронировании теннисного корта).
У них также есть цены на эти услуги. Эта цена говорит о том, что каждый день (в течение срока действия прайс-листа) услуга стоит то и другое между этим и тем часом. Вы можете забронировать услугу в разных ценовых диапазонах. То есть, если в прайс-листе указано, что услуга стоит 90 с 8:00 до 10:00 и с 50:00 с 10:00 до 11:00, то вы можете бронировать с 9 до 11 часов. Тогда к вашему бронированию применимы два ценовых диапазона.
Третья таблица содержит информацию о том, какой чанк (слот) определенной услуги был зарезервирован.
Сначала я запрашиваю service_slots для доступных чанков, а затем мне нужно получить цену за всю длительность чанка, зная, что цена может измениться в середине продолжительности чанка.
Надеюсь, я с ума схожу, более ясно на этот раз
1 ответ
Тяжело отредактировано, так старая почта ушла!
Сначала проверьте мои коды.
Мой тестовый стол:
CREATE TABLE IF NOT EXISTS price(
id INT(20) NOT NULL AUTO_INCREMENT PRIMARY KEY,
pid INT(20) NOT NULL,
staring_time DATETIME,
ending_time DATETIME,
price INT(20) NOT NULL
);
И запросы:
SET @start_pref = '2014-02-07 02:00:00';
SET @end_pref = '2014-02-07 04:00:00';
SELECT
*,
(
SELECT id
FROM price
WHERE
pid = p.pid AND
starting_time <= @start_pref AND
ending_time > @start_pref
) AS id_first,
(
SELECT id
FROM price
WHERE
pid = p.pid AND
ending_time >= @end_pref AND
starting_time < @end_pref
) AS id_last,
(
SELECT IF(
id_first = id_last,
(
SELECT HOUR(TIMEDIFF(@end_pref, @start_pref)*price)
FROM price
WHERE id = id_first AND pid = p.pid
),
(
(
SELECT HOUR(TIMEDIFF(ending_time, @start_pref)*price)
FROM price
WHERE id = id_first AND pid = p.pid
) + (
SELECT HOUR(TIMEDIFF(@end_pref, starting_time)*price)
FROM price
WHERE id = id_last AND pid = p.pid
)
)
) FROM price WHERE pid = p.pid AND id = id_first
) AS total
FROM price p
WHERE
starting_time <= @start_pref AND @start_pref < ending_time
ORDER BY total ASC;
Это работает только тогда, когда @start_pref и @end_pref покрывают 1 - 2 последовательных временных графика.
Тем не менее, это не работает, когда привилегированное время охватывает более 2 записей.
Пример:
Starting pref time: 1am
Ending pref time: 5am
For one specific provider
1am - 2am - $10
2am - 3am - $20
4am - 5am - $30
Это потому, что я не думал об этом заранее, когда начал и закончил свой запрос.
Теперь, если это два или более, вам нужно больше подзапросов, чтобы найти эти идентификаторы, а затем добавить их на мой SELECT IF(
подзапрос.
Также обратите внимание, как я добавил / добавил столбец id
? Так что я могу легко сказать, если это id
принадлежит к тому же pid
на текущий запрос.
PID - это идентификатор провайдера.
Весь скрипт sql.