За последние 24 часа нас посетили 30413 программистов и 1754 робота. Сейчас ищут 854 программиста ...

Работа с датами (решено)

Тема в разделе "MySQL", создана пользователем tchk, 8 дек 2012.

  1. tchk

    tchk Активный пользователь

    С нами с:
    8 дек 2012
    Сообщения:
    10
    Симпатии:
    0
    Народ, прошу помощь умной мыслью...
    На какие таблицы разбить данные чтоб потом можно было адекватно считать:

    Есть отель(не один но пока не принципиально), цена номера за сутки в период с-по:
    date_from | date_till | price
    2012-01-01 | 2012-01-10 | 50
    2012-01-11 | 2012-03-15 | 30
    2012-03-16 | 2012-07-02 | 60

    Нужно посчитать стоимость проживания например с 2012-01-05 по 2012-01-13

    Все что пока придумал:
    1) разбить данные на 365 строк, а потом делать запрос
    SELECT SUM(price) from table WHERE date BETWEEN 2012-01-05 AND 2012-01-13
    в этом случае 365 дней * 500 отелей = 182 500 строк однотипной информации (а еще надо думать над високосными годами)
    2) Писать данные прямо как есть, а потом из PHP делать запрос WHILE-ом отдельно на каждую дату
    SELET price FROM table WHERE date_from <="2012-01-05" AND date_till >= "2012-01-05"
    SELET price FROM table WHERE date_from <="2012-01-05" AND date_till >= "2012-01-05" ...
    и суммировать price в PHP. Что при выборке 50 отелей на 14 дней получается 700 запросов...
     
  2. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.128
    Симпатии:
    1.248
    Адрес:
    там-сям
    Re: Помогите со структурой БД (работа с датами)

    можно обойтись и без разбиения на 365 строк. хотя идея любопытная )))
    применить что-то типа select sum(num_days * price) где num_days будет вычисленным значением из подзапроса по датам
    если сам не догонишь, я попробую протестировать это в реальных таблицах чуть позже…
     
  3. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.128
    Симпатии:
    1.248
    Адрес:
    там-сям
    Re: Помогите со структурой БД (работа с датами)

    вот что выродилось:
    Код (Text):
    1.  
    2. /* Эта хитрая хрень с DATEDIFF дает нам количество дней */
    3. SELECT SUM((DATEDIFF(rc.d2, rc.d1) + 1) * rc.price) AS cost
    4. FROM (
    5.   SELECT
    6.     GREATEST(:dfrom, rp.d_from) AS d1,
    7.     LEAST(:dto, rp.d_to) AS d2,
    8.     rp.price
    9.   FROM `room_prices` AS rp
    10.   WHERE
    11.     /* эта хрень даст нам пересечение цены за нужный диапазон дат.
    12.        выборка быстрая по Primary Key */
    13.     (rp.hotel_id = :hotel AND rp.room_no = :room) AND
    14.     (rp.d_from BETWEEN :dfrom AND :dto OR
    15.      rp.d_to   BETWEEN :dfrom AND :dto) ) AS rc
    предполагается, что таблица room_prices полностью и без дыр покрывает нужные периоды.
    первичный ключ (hotel_id, room_no, d_from)

    Добавлено спустя 15 минут 48 секунд:
    Например:
    room_prices(hotel_id, room_no, d_from, d_to, price):
    Код (Text):
    1.  
    2. 1   101 2012-01-01  2012-01-07  50.00
    3. 1   101 2012-01-08  2012-01-31  25.00
    4. 1   101 2012-02-01  2012-02-29  20.00
    фигачим запрос по комнате 101 в первом отеле с 3 по 15 января. это пересекает два периода в нашей таблице цен
    Код (Text):
    1.  
    2. SELECT SUM((DATEDIFF(rc.d2, rc.d1) + 1) * rc.price) AS cost
    3. FROM (
    4.   SELECT
    5.     GREATEST(DATE '2012-01-03', rp.d_from) AS d1,
    6.     LEAST(DATE '2012-01-15', rp.d_to) AS d2,
    7.     rp.price
    8.   FROM `room_prices` AS rp
    9.   WHERE
    10.     (rp.hotel_id=1 AND rp.room_no='101') AND
    11.     (rp.d_from BETWEEN DATE '2012-01-03' AND DATE '2012-01-15' OR
    12.      rp.d_to   BETWEEN DATE '2012-01-03' AND DATE '2012-01-15') ) AS rc
    внутренний подзапрос вернет:
    Код (Text):
    1.  
    2. 2012-01-03  2012-01-07  50.00
    3. 2012-01-08  2012-01-15  25.00
    общий итог в sum(): 450.00 == 5*50+8*25

    дамп базы: http://zalil.ru/34048536
     
  4. tchk

    tchk Активный пользователь

    С нами с:
    8 дек 2012
    Сообщения:
    10
    Симпатии:
    0
    Re: Помогите со структурой БД (работа с датами)

    Только собрался писать про эту самую хитрую единицу, обновился а ты ее присобачил уже :)
    У меня правда мысль куда-то опять завернула не в ту степь и получилось
    Код (Text):
    1. ... SUM((TO_DAYS(rc.d2)+1-TO_DAYS(rc.d1))*price) AS cost ...
    в твоем варианте красивее :)
    А вот за
    Огромное спасибо
     
  5. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.128
    Симпатии:
    1.248
    Адрес:
    там-сям
    На здоровье!