как лучше проектировать БД в этой ситуации - PullRequest
1 голос
/ 12 января 2012

На первый взгляд схема базы данных выглядит следующим образом:

enter image description here

Схема должна быть в 3-й нормальной форме (и я знаю, что hotels.average_rating предлагает иное, попробуйте следить за этим, поскольку база данных еще не полностью разработана). Это для туристической системы рекомендаций.

SQL:

SET SQL_MODE="NO_AUTO_VALUE_ON_ZERO";
SET time_zone = "+00:00";

CREATE TABLE `activities` (
  `activity_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `activity_name` varchar(277) COLLATE utf8_bin NOT NULL,
  PRIMARY KEY (`activity_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;

CREATE TABLE `bookings` (
  `from_date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  `to_date` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
  `belong_user` int(10) unsigned NOT NULL,
  `belong_hotel` int(10) unsigned NOT NULL,
  `rating` int(3) unsigned NOT NULL,
  KEY `belong_user` (`belong_user`),
  KEY `belong_hotel` (`belong_hotel`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;

CREATE TABLE `countries` (
  `cuntry_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `country_name` varchar(20) COLLATE utf8_bin NOT NULL,
  PRIMARY KEY (`cuntry_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;

CREATE TABLE `hotels` (
  `hotel_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `hotel_name` varchar(128) COLLATE utf8_bin NOT NULL,
  `hotel_stars` int(3) NOT NULL,
  `hotel_description` text COLLATE utf8_bin NOT NULL,
  `average_price` float unsigned NOT NULL,
  `average_rating` float unsigned NOT NULL,
  `total_rooms` int(10) unsigned NOT NULL,
  `free_rooms` int(10) unsigned NOT NULL,
  `belong_region` int(10) unsigned NOT NULL,
  PRIMARY KEY (`hotel_id`),
  KEY `belong_region` (`belong_region`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;

CREATE TABLE `hotels_activity_offers` (
  `belong_hotel` int(10) unsigned NOT NULL,
  `belong_activity` int(10) unsigned NOT NULL,
  UNIQUE KEY `belong_hotel_2` (`belong_hotel`,`belong_activity`),
  KEY `belong_hotel` (`belong_hotel`),
  KEY `belong_activity` (`belong_activity`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;

CREATE TABLE `regions` (
  `region_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `belong_country` int(10) unsigned NOT NULL,
  `region_name` varchar(255) COLLATE utf8_bin NOT NULL,
  PRIMARY KEY (`region_id`),
  KEY `belong_country` (`belong_country`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;

CREATE TABLE `regions_activity_offers` (
  `belong_region` int(10) unsigned NOT NULL,
  `belong_activity` int(10) unsigned NOT NULL,
  KEY `belong_region` (`belong_region`),
  KEY `belong_activity` (`belong_activity`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;

CREATE TABLE `users` (
  `user_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `username` varchar(20) COLLATE utf8_bin NOT NULL,
  `password` varchar(40) COLLATE utf8_bin NOT NULL COMMENT 'MD5',
  `first_name` varchar(20) COLLATE utf8_bin NOT NULL,
  `last_name` varchar(20) COLLATE utf8_bin NOT NULL,
  `email` varchar(255) COLLATE utf8_bin NOT NULL,
  `is_admin` tinyint(1) NOT NULL,
  `is_active` tinyint(1) NOT NULL,
  PRIMARY KEY (`user_id`),
  KEY `is_active` (`is_active`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;

CREATE TABLE `users_favourite_activities` (
  `belong_user` int(10) unsigned NOT NULL,
  `belong_activity` int(10) unsigned NOT NULL,
  UNIQUE KEY `belong_user_2` (`belong_user`,`belong_activity`),
  KEY `belong_user` (`belong_user`),
  KEY `belong_activity` (`belong_activity`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;


ALTER TABLE `bookings`
  ADD CONSTRAINT `bookings_ibfk_3` FOREIGN KEY (`belong_hotel`) REFERENCES `hotels` (`hotel_id`) ON DELETE CASCADE,
  ADD CONSTRAINT `bookings_ibfk_2` FOREIGN KEY (`belong_user`) REFERENCES `users` (`user_id`) ON DELETE CASCADE;

ALTER TABLE `hotels`
  ADD CONSTRAINT `hotels_ibfk_1` FOREIGN KEY (`belong_region`) REFERENCES `regions` (`region_id`) ON DELETE CASCADE;

ALTER TABLE `hotels_activity_offers`
  ADD CONSTRAINT `hotels_activity_offers_ibfk_2` FOREIGN KEY (`belong_activity`) REFERENCES `activities` (`activity_id`) ON DELETE CASCADE,
  ADD CONSTRAINT `hotels_activity_offers_ibfk_1` FOREIGN KEY (`belong_hotel`) REFERENCES `hotels` (`hotel_id`) ON DELETE CASCADE;

ALTER TABLE `regions`
  ADD CONSTRAINT `regions_ibfk_1` FOREIGN KEY (`belong_country`) REFERENCES `countries` (`cuntry_id`) ON DELETE CASCADE;

ALTER TABLE `regions_activity_offers`
  ADD CONSTRAINT `regions_activity_offers_ibfk_2` FOREIGN KEY (`belong_activity`) REFERENCES `activities` (`activity_id`) ON DELETE CASCADE,
  ADD CONSTRAINT `regions_activity_offers_ibfk_1` FOREIGN KEY (`belong_region`) REFERENCES `regions` (`region_id`) ON DELETE CASCADE;

ALTER TABLE `users_favourite_activities`
  ADD CONSTRAINT `users_favourite_activities_ibfk_1` FOREIGN KEY (`belong_user`) REFERENCES `users` (`user_id`) ON DELETE CASCADE,
  ADD CONSTRAINT `users_favourite_activities_ibfk_2` FOREIGN KEY (`belong_activity`) REFERENCES `activities` (`activity_id`) ON DELETE CASCADE;
  1. Вопрос в следующем: как лучше всего добавить функцию "Журнал действий пользователя", в которой хранятся действия, в которых принял участие пользователь? Обратите внимание, что как в регионах, так и в отелях могут быть действия, и необходимо уметь определить, проводилась ли эта деятельность в регионе или в отеле. Ссылочная целостность должна быть гарантирована.

  2. Представить запрос (он должен использовать JOIN, не так ли?) , в котором перечислены все пользователи и их действия вместе с идентификатором отеля или идентификатор региона . (тот, который не применим, может быть НЕДЕЙСТВИТЕЛЕН, если требуется).

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

1 Ответ

0 голосов
/ 12 января 2012

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

hotels.average_rating?

WTF

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

...