SQLinfo.ru - Все о MySQL

Форум пользователей MySQL

Задавайте вопросы, мы ответим

Вы не зашли.

#1 23.12.2013 22:33:07

deadka
Администратор
Зарегистрирован: 14.11.2007
Сообщений: 2422

Отношение многие ко многим без лишних джоинов

Приветствую, коллеги!

"ТЗ" моей задачи звучит следующим образом.

В системе есть региональные разделы, где размещаются наблюдения определенных видов трав.
Наблюдение содержит в себе один вид.
Каждый раздел "описывает" лишь несколько видов из общего множества.
При этом один и тот же вид может присутствовать в нескольких разделах, то есть ромашка может быть и в алтайском и в красноярских разделах.

Хотелось бы, чтобы наблюдение ссылалось напрямую на раздел и на вид, чтобы не делать лишних джоинов в запросах. В то же время, чтобы структура была нормализованной.

Придумал следующий вариант:

Виды (species) и разделы (section) - это явно многие ко многим =>
Таблица rel_section_species содержит в себе два поля - (species_id,section_id), их связка образует собой первичный ключ.
Таблица наблюдений - observation содержит в себе вторичный ключ, который ссылается на первичный ключ rel_section_species.


DROP TABLE IF EXISTS `observation`;
DROP TABLE IF EXISTS `rel_section_species`;
DROP TABLE IF EXISTS `species`;
DROP TABLE IF EXISTS `section`;

CREATE TABLE  `section` (
  `id` bigint(20) NOT NULL primary key,
  `name` varchar(255) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
insert into `section` values(1,'section1'),(2,'section2');

CREATE TABLE  `species` (
  `id` bigint(20) NOT NULL primary key,
  `name` varchar(255) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
insert into `species` values(1,'species1'),(2,'species2');


CREATE TABLE  `rel_section_species` (
  `section_id` bigint(20) NOT NULL,
  `species_id` bigint(20) NOT NULL,
  PRIMARY KEY (`section_id`,`species_id`),
  KEY `section_id` (`section_id`),
  KEY `species_id` (`species_id`),
  CONSTRAINT `constraint__section_id` FOREIGN KEY (`section_id`) REFERENCES `section` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
  CONSTRAINT `constraint__species_id` FOREIGN KEY (`species_id`) REFERENCES `species` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
insert into rel_section_species values(1,1),(2,1),(1,2);

CREATE TABLE  `observation` (
  `id` bigint(20) NOT NULL primary key auto_increment,
  `section_id` bigint(20) NOT NULL,
  `species_id` bigint(20) NOT NULL,
  KEY `section_id` (`section_id`),
  KEY `species_id` (`species_id`),
  CONSTRAINT `observation__rel_ss__section_id__species_id` FOREIGN KEY (`section_id`,`species_id`) REFERENCES `rel_section_species` (`section_id`,`species_id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
insert into observation(section_id,species_id) values(1,1),(2,1),(1,2);
 


Первый вид может находиться и в первом и во втором разделе,
а второй вид - есть только в первом разделе.

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

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

Вот. Покритикуйте пожалуйста, если какие-то блохи видны.
Или я чего-то упустил и можно как-то проще?


Зеленый свет для слабаков, долги отдают только трусы, тру гики работают только в консоли...

Неактивен

 

#2 25.12.2013 02:59:44

rgbeast
Администратор
MySQL Authorized Developer and DBA
Откуда: Москва
Зарегистрирован: 21.01.2007
Сообщений: 3880

Re: Отношение многие ко многим без лишних джоинов

Данил, все нормально, вроде бы

Неактивен

 

Board footer

Работает на PunBB
© Copyright 2002–2008 Rickard Andersson