Форум: Форум PHPФорум ApacheФорум Регулярные ВыраженияФорум MySQLHTML+CSS+JavaScriptФорум FlashРазное
Новые темы: 0000000
Объектно-ориентированное программирование на PHP. Авторы: Кузнецов М.В., Симдянов И.В. PHP на примерах (2 издание). Авторы: Кузнецов М.В., Симдянов И.В. Самоучитель MySQL 5. Авторы: Кузнецов М.В., Симдянов И.В. PHP 5/6. В подлиннике. Авторы: Кузнецов М.В., Симдянов И.В. MySQL 5. В подлиннике. Авторы: Кузнецов М.В., Симдянов И.В.
ВСЕ НАШИ КНИГИ
Консультационный центр SoftTime

Форум MySQL

Выбрать другой форум

 

Здравствуйте, Посетитель!

вид форума:
Линейный форум Структурный форум

тема: Проектирование базы
 
 автор: Лена   (22.12.2010 в 13:57)   письмо автору
50.9 Кб
 
 

Пишу админку.
Есть отели, типы номеров в них, в номерах - атрибуты(удобства).
Есть даты заезда в эти отели в определенный тип номера.
2 даты заезда к определенному типу номера пишутся в колонке сверху. См. рисунок в аттаче.

У меня подозрение, что относительно даты и цен я спроектировала неправильно.
Потому как не получается вывести столбцы в таблицу с датой и ценами за эти даты к определенному типу номера.



CREATE TABLE `rnt1_hotel` (
  `id` int(11) NOT NULL auto_increment,
  `name` varchar(255) NOT NULL,
  PRIMARY KEY  (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=3 DEFAULT CHARSET=utf8 AUTO_INCREMENT=3 ;

CREATE TABLE `rnt1_room` (
  `id` int(11) NOT NULL auto_increment,
  `type_room` varchar(255) NOT NULL,
  `id_hotel` int(11) NOT NULL,
  PRIMARY KEY  (`id`),
  KEY `id_hotel` (`id_hotel`)
) ENGINE=MyISAM AUTO_INCREMENT=5 DEFAULT CHARSET=utf8 AUTO_INCREMENT=5 ;

CREATE TABLE `rnt1_date` (
  `id` int(11) NOT NULL auto_increment,
  `date` date NOT NULL,
  `id_type_room` int(11) NOT NULL,
  PRIMARY KEY  (`id`),
  KEY `id_type_room` (`id_type_room`)
) ENGINE=MyISAM AUTO_INCREMENT=9 DEFAULT CHARSET=utf8 AUTO_INCREMENT=9 ;

CREATE TABLE `rnt1_price` (
  `id` int(11) NOT NULL auto_increment,
  `price` int(11) default NULL,
  `id_hotel` int(11) NOT NULL,
  `id_type_room` int(11) NOT NULL,
  `id_date` int(11) NOT NULL,
  PRIMARY KEY  (`id`),
  KEY `id_hotel` (`id_hotel`,`id_type_room`,`id_date`)
) ENGINE=MyISAM AUTO_INCREMENT=9 DEFAULT CHARSET=utf8 AUTO_INCREMENT=9 ;

  Ответить  
 
 автор: Trianon   (22.12.2010 в 14:29)   письмо автору
 
   для: Лена   (22.12.2010 в 13:57)
 

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

  Ответить  
 
 автор: Лена   (22.12.2010 в 14:51)   письмо автору
 
   для: Trianon   (22.12.2010 в 14:29)
 

У каждого отеля есть определенные дни заезда - в таблице пишется по две даты в одном столбце.
Все это касается бронирования отелей.
Получается, дата - аттрибут отеля и выходит, надо делать таблицу даты и в ней поле id_hotel - соотнесенность даты к определенному отелю.

  Ответить  
 
 автор: Trianon   (22.12.2010 в 14:53)   письмо автору
 
   для: Лена   (22.12.2010 в 14:51)
 

Ээээ...это как?
В другие дни отель не допускает заселение ни для кого?
Что-то не верю вообще.

  Ответить  
 
 автор: Лена   (22.12.2010 в 15:09)   письмо автору
 
   для: Trianon   (22.12.2010 в 14:53)
 

Запуталась совсем...
Не так. В отеле есть типы комнат. В определенные дни доступны по определенной цене какие-то типы комнат. Каждую дату, получается, надо привязать к определенному отелю и к определенному типу комнат в нем. Только там в столбце по две даты. Каждую из них мы привяжем, а как их вместе вывести по парам?

  Ответить  
 
 автор: Trianon   (22.12.2010 в 15:34)   письмо автору
 
   для: Лена   (22.12.2010 в 15:09)
 

отели                         типы номеров
  \                             /
  -- связка с датой и  ценой -

  Ответить  
 
 автор: Лена   (22.12.2010 в 17:18)   письмо автору
 
   для: Trianon   (22.12.2010 в 15:34)
 

что ж это получается...
мне надо таблицу-связку делать, где я укажу id_hotel - id_room_type - id_date - id_price?
таблица с датами, и таблица с ценами тогда остается

  Ответить  
 
 автор: Trianon   (22.12.2010 в 18:11)   письмо автору
 
   для: Лена   (22.12.2010 в 17:18)
 

почему id_date и id_price?

почему не просто дату и цену?

Нет ну то есть если эта цена - некоторое специальное коммерческое предложение, имеющее сввою запись в таблице прайса с кучей сопутствующих свойств - тогда конечно.
Но на пустом месте-то зачем?

  Ответить  
 
 автор: Лена   (23.12.2010 в 01:35)   письмо автору
5.6 Кб
 
   для: Trianon   (22.12.2010 в 18:11)
 

Исправила, спасибо.
Все равно делаю вывод и в выводе не получается ни даты, ни цены вывести.
Уже один запрос с JOIN`ами разбила на несколько, каждый из которых работает только с одной таблицей, все равно шапка таблицы, где дата, выводится неправильно. Лишнее выводится.
Получается теперь я вывожу в цикле отели, внутри этого цикла - типы комнат в отеле, внутри этого - еще один цикл, который служит для вывода дат и цен.
Но у меня даты и цены к датам выводятся в разных местах таблицы.

Я скрипт для наглядности прикрепила.

  Ответить  
 
 автор: Trianon   (23.12.2010 в 08:58)   письмо автору
 
   для: Лена   (23.12.2010 в 01:35)
 

>Исправила, спасибо.
какая структура получилась в результате?

  Ответить  
 
 автор: Лена   (23.12.2010 в 10:13)   письмо автору
 
   для: Trianon   (23.12.2010 в 08:58)
 


-- Структура таблицы `rnt1_hotel`
--

CREATE TABLE `rnt1_hotel` (
  `id` int(11) NOT NULL auto_increment,
  `name` varchar(255) NOT NULL,
  `visible` varchar(2) NOT NULL,
  PRIMARY KEY  (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=3 DEFAULT CHARSET=utf8 AUTO_INCREMENT=3 ;


CREATE TABLE `rnt1_room` (
  `id` int(11) NOT NULL auto_increment,
  `type_room` varchar(255) NOT NULL,
  `id_hotel` int(11) NOT NULL,
  `visible` varchar(2) NOT NULL,
  PRIMARY KEY  (`id`),
  KEY `id_hotel` (`id_hotel`)
) ENGINE=MyISAM AUTO_INCREMENT=5 DEFAULT CHARSET=utf8 AUTO_INCREMENT=5 ;

CREATE TABLE `rnt1_room_attrs` (
  `id` int(11) NOT NULL auto_increment,
  `price` int(11) NOT NULL,
  `date` date NOT NULL,
  `id_room` int(11) NOT NULL,
  `id_hotel` int(11) NOT NULL,
  `visible` varchar(2) default NULL,
  PRIMARY KEY  (`id`),
  KEY `id_hotel` (`id_hotel`),
  KEY `id_room` (`id_room`),
  KEY `id_room_2` (`id_room`)
) ENGINE=MyISAM AUTO_INCREMENT=9 DEFAULT CHARSET=utf8 AUTO_INCREMENT=9 ;

  Ответить  
 
 автор: Лена   (23.12.2010 в 16:09)   письмо автору
 
   для: Лена   (23.12.2010 в 10:13)
 

Как оказалось, даты - это интервалы стоимости, например,
интервал1
даты 28.12.2010-09.01.2011 стоимость 120дол для определенных типов номеров,
интервал2
даты 01.11.2010-01.04.2011 стоимость 90дол

После эти интервалы вводятся в поиске, т.е. нужно будет делать сортировку по начальной и конечной дате интервала.

Получается, надо создавать отдельную таблицу для интервалов дат:
id - date_start - date_end и связывать ее по ключу с таблицей, где лежит цена.

  Ответить  
 
 автор: Zilog   (23.12.2010 в 23:51)   письмо автору
 
   для: Лена   (23.12.2010 в 16:09)
 

>Получается, надо создавать отдельную таблицу для интервалов дат:
>id - date_start - date_end и связывать ее по ключу с таблицей, где лежит цена.

Конечно.
Сам мучался когда делал, кстати, сами даты я хранил по другому, но неизвестно, правильно ли: у меня дата как timestamp, так удобно считать периоды и чего-то ещё, уже не помню, но проблема возникнет при смене года, все интервалы разом устареют и их для правильной работы придётся обновить. Другого способа хранить интервал пока не придумал, вот скоро вернусь к этой задаче.

  Ответить  
 
 автор: Trianon   (23.12.2010 в 23:56)   письмо автору
 
   для: Лена   (23.12.2010 в 16:09)
 

Именно.
Только интервалы удобнее задавать открытыми справа отрезками. [a b[
Иначе код, вычисления пересечения окажется сильно сложным, соответственно усложнятся запросы по условию наложения интервалов, а значит и прикладной код добавления нового интервала.

  Ответить  
 
 автор: Zilog   (24.12.2010 в 00:11)   письмо автору
 
   для: Trianon   (23.12.2010 в 23:56)
 

>Только интервалы удобнее задавать открытыми справа отрезками. [a b[

ммм... то есть? только даты начала периода?
но ведь это не отменяет проблему смены года.

для Лены: и ещё, у вас возможно всплывёт вопрос с високосными годами и минутами-секундами.

  Ответить  
 
 автор: Trianon   (24.12.2010 в 00:21)   письмо автору
 
   для: Zilog   (24.12.2010 в 00:11)
 

>>Только интервалы удобнее задавать открытыми справа отрезками. [a b[
>ммм... то есть?
математика, 4-й класс.

только даты начала периода?
только дата начала - это уже луч.
почему?
момент завершения периода тоже хранить нужно.

>для Лены: и ещё, у вас возможно всплывёт вопрос с високосными годами и минутами-секундами.

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

  Ответить  
 
 автор: Zilog   (24.12.2010 в 01:14)   письмо автору
 
   для: Trianon   (24.12.2010 в 00:21)
 

>момент завершения периода тоже хранить нужно.

ну, так так и храним. Я не понял формулировку про "открытые отрезки". Что значит открытые? Не серчай, 4 класс давно был :)

>>для Лены: и ещё, у вас возможно всплывёт вопрос с високосными годами и минутами-
>Ниичего там не всплывет. (То есть всплывет, и многое, оно всяко не это :))
>моменты времени абсолютные, потому что цены привязаны к сезонам конкретного года.

Ну как не всплывёт? Если время в начало/конец периода указывать 00:00:00/23:59:59, то конечно не всплывёт. А если просто датами оперировать - то всплывёт, ибо при записи в БД он туда текущую сунет. А тут это важно — ибо расчёт в гостиницах требует точности, более того, там ещё куча нюансов. Например, если ОТ в этом году, ДО - в следующем. Или между ОТ и ДО целиком несколько периодов, но это уже другая задача.

upd1. Да, ещё помню был геморой с переводом часов в летнее/зимнее время — так вообще пришлось к грнвичу прибегнуть.

upd2. Да, високосные не причём. Перепутал с переводом стрелок, а то помню что с чем-то намучился :)

  Ответить  
 
 автор: Trianon   (24.12.2010 в 01:34)   письмо автору
 
   для: Zilog   (24.12.2010 в 01:14)
 

>>момент завершения периода тоже хранить нужно.
>
>ну, так так и храним. Я не понял формулировку про "открытые отрезки". Что значит открытые? Не серчай, 4 класс давно был :)

Неужто давнее, чем у меня? :)

к примеру, эта неделя (по российской локали):
Закрытый отрезок [20 декабря .... 26 декабря]
Открытый отрезок [20 декабря .... 27 декабря[

Эти сутки:
Закрытый отрезок: [24дек/00:00 ... 24дек/23:59]
Открытый отрезок [24дек/00:00 ... 25дек/00:00[
и т.п.


>>>для Лены: и ещё, у вас возможно всплывёт вопрос с високосными годами и минутами-
>>Ниичего там не всплывет. (То есть всплывет, и многое, оно всяко не это :))
>>моменты времени абсолютные, потому что цены привязаны к сезонам конкретного года.
>
>Ну как не всплывёт? Если время в начало/конец периода указывать 00:00:00/23:59:59, то конечно не всплывёт. А если просто датами оперировать - то всплывёт, ибо при записи в БД он туда текущую сунет.
В поле data кроме даты сложно что-то сунуть. Хотя с точными моментами возни меньше.

  Ответить  
 
 автор: Zilog   (24.12.2010 в 01:45)   письмо автору
 
   для: Trianon   (24.12.2010 в 01:34)
 

>Неужто давнее, чем у меня? :)
не думаю, скорее всего у меня в этой части мозга регенерация памяти нестабильно работает :)

>к примеру, эта неделя (по российской локали):
>Закрытый отрезок [20 декабря .... 26 декабря]
>Открытый отрезок [20 декабря .... 27 декабря[

ясно, спасибо. Я хранил данные закрытыми отрезками. Сейчас выясняется, что лучше открытыми. Чем? Как это упростит работу?

В своей админке я сделал так: юзер задаёт только даты начала периодов. Конечная дата ("закрытая") вычисляется автоматически. Проблем с расчётом цен по сезонам особых не помню (только на гринвича пришлось перейти), алгоритм получился не такой уж и сложный. Так чем открытые даты могут упростить код?

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

Вот как у меня это работало:

код нашёл, но что то он слишком великоват, что бы его сюда постить. может дейстительно стоит подумать над оптимизацией? :)

  Ответить  
 
 автор: Trianon   (24.12.2010 в 02:38)   письмо автору
 
   для: Zilog   (24.12.2010 в 01:45)
 

Если есть интервалы времени, обычно (при добавлении очередного интервала чаще всего, но не только) приходится решать задачи вычисления пересечения интервалов, а иногда разности и объединения.
Дано:           ааааааааааааа
             bbbbbbbb

Найти:          ссссс


На открытых отрезках оно вычисляется на раз.
На закрытых - нудно и противно.
А если это вычисление нужно в условие JOIN ON закатать, так там вообще крышка настает.

  Ответить  
 
 автор: Zilog   (24.12.2010 в 15:12)   письмо автору
 
   для: Trianon   (24.12.2010 в 02:38)
 

>На открытых отрезках оно вычисляется на раз.
>На закрытых - нудно и противно.
>А если это вычисление нужно в условие JOIN ON закатать, так там вообще крышка настает.

Тема интересная, важная. Надо будет в отдельный топик вынести, наверняка ещё много кому понадобится.

  Ответить  
 
 автор: Лена   (24.12.2010 в 01:39)   письмо автору
26 Кб
 
   для: Zilog   (24.12.2010 в 01:14)
 

У меня формат даты в базе - date.
Только что поиск дописала, запросы были типа:
SELECT *
FROM rnt1_room_attrs
WHERE id_hotel =1
AND (
(
date_start >= '2010-12-01'
AND date_start < '2010-12-24'
)
OR (
date_end >= '2010-12-01'
AND date_end < '2010-12-24'
)
)
AND price <=100
LIMIT 0 , 20

Не получается разложить таблицу в админке. Диапазоны дат - указала, цены неправильно выводятся. В чем проблема, я поняла, как из нее выйти, не знаю.
Должно получиться так, как на картинке - см. аттач. Значения, обведенные красным, не должны быть - здесь окна должны быть пустыми.
Как делала.
Вывела даты в шапке, берем диапазоны, которые принадлежат определенному отелю:
$q2 = "SELECT * FROM rnt1_room_attrs WHERE id_hotel=" . $row['hid'];
дальше в цикле я вывожу шапку.
Цены мне надо вывести ниже, причем сделать столько столбцов. как в шапке.
Делаю ниже еще раз этот запрос, и опять вывожу в цикле цены.
И получается, что у меня во всех ячейках - одинаковые значения. Т.е. там, где за определенный диапазон даты цены нет(в ячейке должно быть пусто), у меня заполнено.
Привожу кусок кода, который выводит одну строку таблицы:
ТИП КОМНАТЫ- ЦЕНЫ ЗА ПЕРИОДЫ


            <tr bgcolor="#DFE0FF">
            <td align="center" >
                <input type="checkbox" name="sel[]" value="<?php print $row1['id']?><?php print $checked;?>>
            </td>
                <td  width="300" align="center"><nobr><span style="padding:7px;">
                <?php print $row1['type_room']?></span></nobr>
                </td>
                <td>
                <table border="1" width="100%" cellpadding=5 cellspacing=0><tr>
<?php

                $qw 
"SELECT * FROM rnt1_room_attrs rra1
                WHERE id_hotel=" 
$row['hid'];
                
$resw mysql_query($qw);
                if(!
$res5) exit("Error in " $qw mysql_error());

              while(
$roww=mysql_fetch_assoc($resw)){

                if(
ЗДЕСЬ НАДО ЗАДАТЬ ДЛЯ ЦЕНЫ УСЛОВИЕЧТОБЫ СОГЛАСОВАТЬ ЦЕНУ С ДАТОЙ){
?>
                    <td width="50" align="center"><input type="text" value="<?php print $roww['price']?>" name="price1"></td>
<?php
                
}else{

?>                   <td width="50" align="center"><input type="text" value="" name="price1"></td>

<?php
                
}
                }
?>
            </tr></table>
            </td>
            </tr>


Как мне правильно разложить таблицу по горизонтали?
Если кто-то делал, помогите, пожалуйста.

  Ответить  
 
 автор: Zilog   (24.12.2010 в 01:47)   письмо автору
 
   для: Лена   (24.12.2010 в 01:39)
 

>Как мне правильно разложить таблицу по горизонтали?
>Если кто-то делал, помогите, пожалуйста.

Лена, почитайте, что мы с Трианоном тут наговорили. Боюсь, если вы не внесётсе на этом этапе существенные изменения в логику работы вашего алгоритма, потом вам придётся очень много переделывать. А таблицу разложить всегда можно успеть.

Да, думаю задачка не так проста, как она вам представляется.

  Ответить  
 
 автор: deimand   (24.12.2010 в 02:30)   письмо автору
 
   для: Лена   (22.12.2010 в 13:57)
 

может поможет http://red-stones.ru/test/reserve/

  Ответить  
Rambler's Top100
вверх

Rambler's Top100 Яндекс.Метрика Яндекс цитирования