【问题标题】:how to best design the DB in this situation在这种情况下如何最好地设计数据库
【发布时间】:2012-01-12 14:14:55
【问题描述】:

一目了然,数据库架构如下所示:

模式必须是第 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 不是吗?)列出所有用户及其活动以及酒店 ID region id.(不适用的可以为NULL)。

简单的解决方案更好 - 所以最好不要存储过程或任何在 mysql 特定功能中挖掘太多的东西。

【问题讨论】:

  • 与此类似(如果不相同):stackoverflow.com/questions/5537779/…
  • 酒店属于区域。区域活动优惠是否适用于区域内的所有酒店,或者区域活动优惠和酒店活动优惠彼此完全不相关?
  • 一个activity可以直接属于一个区域,如图所示。比如“滑雪”。当然,酒店也可能提供滑雪优惠(例如:全包)。然而,它们“不”相关。
  • 您的某些表没有使用 PRIMARY KEY 或 NOT NULL UNIQUE 声明的键。在你修复它之前,这些表都不可能在 3NF 中。一些“查找”表缺乏对其自然键的唯一约束。 ("country_name", "activity_name".) 还不如在你处理它的时候解决这个问题。
  • @Catcall 请详细说明。每个问题的表格是什么?

标签: mysql sql database database-design relational-database


【解决方案1】:

您的数据库未标准化 - 您完成它的方式看起来像是一个典型的例子,说明为什么标准化是一个好主意。

hotels.average_rating?

WTF?

虽然对数据进行非规范化是有意义的,但这不是如何做到的。想想当用户提交酒店评级时您需要做什么——您需要根据提交的所有评级重新计算该值。相反,如果您持有 sum_of_ratings(甚至保留当前平均值)多个评分,那么您可以根据酒店记录和新评分计算新值,而无需查看其他评分.

【讨论】:

  • 想象一下该领域暂时不存在,而您正在考虑解决实际问题的方法。请改进您的答案,以便它也回答我的问题。 > WTF 将在最终数据库中修复,不用担心 :-)
猜你喜欢
  • 2013-03-14
  • 1970-01-01
  • 2016-04-17
  • 1970-01-01
  • 2011-05-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多