У меня возникли проблемы с приложением, над которым я работаю, и я надеюсь получить руководство.
У меня простая система бронирования: у каждого товара есть стандартная цена, но есть периоды, когда цена может измениться.
Например:
Стандартная цена 100 / день
От Oct. 1st
в Feb. 1st
каждого года цена 80 / день
От Jun. 1st
в Aug. 31st
каждого года цена 120 / день
Поскольку это событие происходит ежегодно, мне нужны только месяц и день, но я не знаю, как сохранить эти значения в базе данных. Я думал о том, чтобы иметь два поля, одно для месяца и одно для дня, которые содержат числовые значения (01-12
на месяц, 01-31
на день). Эти значения устанавливаются самим пользователем, и они относятся к самому элементу, он не установлен для всех.
Проблема в том, что когда кто-то делает бронирование, мне нужно проверить, нужно ли менять цену, и я не понимаю, как составить запрос, чтобы это проверить. Что еще хуже, цена может иметь несколько значений за забронированный период.
Следуя приведенному выше примеру, если бы я забронировал предмет из Sep. 1st (current year)
в Jul. 1st (next year)
, цена будет следующим:
100 / день от Sep. 1st
в Sep. 30th
80 / день от Oct. 1st
в Feb. 1st
100 / день от Feb. 2nd
to May 31st
120 / день от Jun. 1st
в Jul. 1st
Есть ли какой-нибудь способ проверки этих случаев без ежедневного цикла и проверки соответствия базы данных?
Спасибо
Вы можете использовать MySQL date_format
функция при проверке даты.
Например:
select date_format('2016-05-18', '%m%d');
+-----------------------------------+
| date_format('2016-05-18', '%m%d') |
+-----------------------------------+
| 0518 |
+-----------------------------------+
1 row in set (0,01 sec)
Итак, вы можете просто проверить с простым интервалом: сегодня 0518
и между 2 февраля и 31 мая:
0202 <= 0518 <= 0531
Полный пример:
desc mytable;
+-----------+---------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-----------+---------+------+-----+---------+-------+
| date_from | char(4) | YES | | NULL | |
| date_to | char(4) | YES | | NULL | |
| price | int(11) | YES | | NULL | |
+-----------+---------+------+-----+---------+-------+
3 rows in set (0,00 sec)
select * from mytable;
+-----------+---------+-------+
| date_from | date_to | price |
+-----------+---------+-------+
| 0901 | 0930 | 100 |
| 1001 | 0201 | 80 |
| 0202 | 0531 | 100 |
| 0601 | 0701 | 120 |
+-----------+---------+-------+
4 rows in set (0,00 sec)
Пример запроса:
select price, date_from, date_to from mytable where date_format(now(), '%m%d') between date_from and date_to;
+-------+-----------+---------+
| price | date_from | date_to |
+-------+-----------+---------+
| 100 | 0202 | 0531 |
+-------+-----------+---------+
1 row in set (0,01 sec)
РЕДАКТИРОВАТЬ:
Прочитайте ваш комментарий к ответу @ FelipeDuarte … В период с 10/01 (1 октября) по 02/01 (1 февраля) мы должны рассмотреть новый год …
Вы можете обмануть, разделив период на два: с 10 января по 31 декабря и с 01 января по 02 января
Я не знаю ваших таблиц базы данных, но я думаю, что вы могли бы сделать так:
SELECT * from table
WHERE iniDay >= booking_ini_day AND iniMonth >= booking_ini_month -- get initial period
AND iniDay <= booking_end_day AND iniMonth <= booking_end_month
UNION ALL
SELECT * from table
WHERE iniDay <= booking_ini_day AND iniMonth <= booking_ini_month -- get middle periods
AND endDay >= booking_end_day AND endMonth >= booking_end_month
UNION ALL
SELECT * from table
WHERE
endDay >= booking_ini_day AND endMonth >= booking_ini_month
AND endDay <= booking_end_day AND endMonth <= booking_end_month -- get end period
Вы будете «дублировать» информацию базы данных, такую как день, месяц и месяц, но это для лучшей производительности.