Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: Select из разных таблиц с одинаковым ID  (Прочитано 18835 раз)
0 Пользователей и 1 Гость смотрят эту тему.
duke333
Новенький

it
Offline Offline

« : 21-07-2011 00:00 » 

Для хранения артиклей входящих в заказ использую таблицу (order_item)
Код: (MySQL)
CREATE TABLE `order_item` (
  `id_order` int(11) NOT NULL,
  `id_item` int(11) NOT NULL,
  `item_type` varchar(15) NOT NULL,
  `item_index` tinyint(2) unsigned NOT NULL,
  `quantity` smallint(4) unsigned NOT NULL,
  PRIMARY KEY  (`id_order`,`id_item`,`item_type`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

`item_type` - содержит название таблицы в которой содержатсяя данные по артиклю (т.е. service, excursion или accomodation)

Сами же артикли ввиду того что имеют разный характеристики я храну в разных таблицах (service, excursion, accomodation)
Код: (MySQL)
CREATE TABLE `excursion` (
  `id_item` int(11) NOT NULL auto_increment,
  `name` varchar(255) default NULL
...
параметры
...
  PRIMARY KEY  (`id_e`),
  UNIQUE KEY `NewIndex` (`name`)
) ENGINE=MyISAM AUTO_INCREMENT=10 DEFAULT CHARSET=utf8;
таким же образом реалезованы и (service, accomodation)

Вопрос такой: Как по id_order получить список артиклей входящих в заказ?
учитывая что id_item уникален только для своей таблици
Записан
HandKot
Молодой специалист

ru
Offline Offline

« Ответ #1 : 21-07-2011 04:23 » 

вероятно как-то так (правда синтаксис для MS SQL)
Код: (SQL)
SELECT *
FROM order_item oi
LEFT JOIN service s ON s.item_index = oi.item_index AND oi.item_type = 'service'
LEFT JOIN excursion e ON e.item_index = oi.item_index AND oi.item_type = 'excursion'
LEFT JOIN accomodation a ON a.item_index = oi.item_index AND oi.item_type = 'accomodation'
« Последнее редактирование: 21-07-2011 11:13 от x77 » Записан

I Have Nine Lives You Have One Only
THINK!
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #2 : 21-07-2011 10:34 » 

HandKot, в данном случае синтаксис совпадает с ANSI SQL и с MySQL тут полная совместимость.
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Kivals
Команда клуба

ca
Offline Offline
Пол: Мужской

WWW
« Ответ #3 : 21-07-2011 11:10 » 

В таком запросе важно чтобы id_item было уникально во всех таблицах с артиклями, т.е. результат запроса:
Код: (SQL)
SELECT MAX(cnt) FROM
(
  SELECT COUNT(*) AS cnt FROM
  (
    SELECT id_item FROM service
    UNION ALL
    SELECT id_item FROM excursion
    UNION ALL
    SELECT id_item FROM accomodation
  )
  GROUP BY id_item
)
должен быть 1, иначе получим ситуацию, которую уже разбирали здесь:
https://forum.shelek.ru/index.php/topic,27290.msg262661.html#msg262661
Записан
duke333
Новенький

it
Offline Offline

« Ответ #4 : 21-07-2011 11:23 » 

Спасибо! Все работает на мускуле класс!

Тема закрыта!

Добавлено через 16 минут и 52 секунды:
Спасибо! Все работает на мускуле класс!

Тема закрыта!
В таком запросе важно чтобы id_item было уникально во всех таблицах с артиклями, т.е. результат запроса:
Код: (SQL)
SELECT MAX(cnt) FROM
(
  SELECT COUNT(*) AS cnt FROM
  (
    SELECT id_item FROM service
    UNION ALL
    SELECT id_item FROM excursion
    UNION ALL
    SELECT id_item FROM accomodation
  )
  GROUP BY id_item
)
должен быть 1, иначе получим ситуацию, которую уже разбирали здесь:
https://forum.shelek.ru/index.php/topic,27290.msg262661.html#msg262661

т.е. насколько я понял для таблици (service) id_item должен быть уникален, для (excursion и accomodation ) также.
но возможно
service.id_item = 1 и excursion.id_item = 1

я правильно понял ?
« Последнее редактирование: 21-07-2011 11:40 от duke333 » Записан
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #5 : 21-07-2011 15:28 » 

Сквозная уникальность должна быть. Для этого можно создать дополнительную таблицу, которая будет обладать полем auto_increment, а в service, excursion и т.п. таблицах auto_increment надо удалить, но primary key оставить.

Код: (MySQL)
CREATE TABLE item_index
(
  item_id INT UNSIGNED AUTO_INCREMENT,
  PRIMARY KEY (item_id)
);

CREATE TABLE excursion
(
  id_item INT UNSIGNED NOT NULL,
/* ... */
  PRIMARY KEY  (id_item),
/* ... */
);

Поле id_item является PK во всех этих таблицах и в item_index.
Заметь еще UNSIGNED - незачем иметь знаковый тип для идентификатора.

Работать с этим так:
1. Вставка в item_index.
2. Вставка в excursion (или другую аналогичную таблицу) с использованием в качестве идентификатора значение функции LAST_INSERT_ID().
3. Вставка в order_item аналогично п.2.
 
« Последнее редактирование: 21-07-2011 15:31 от RXL » Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Kivals
Команда клуба

ca
Offline Offline
Пол: Мужской

WWW
« Ответ #6 : 21-07-2011 15:33 » 

Я невнимательно вчитался в задание - не обратил внимание на item_type.
С его наличием замечание отпадает и совпадение id_item в таблицах service, excursion или accomodation возможно.

А вообще - согласен с RXL: я бы тоже делал это поле уникальным в рамках всей таблицы order_item

Вообще в последних моих БД было поле object_id, уникальное во всей БД

Добавлено через 1 минуту и 50 секунд:
Работать с этим так:
1. Вставка в item_index.
2. Вставка в excursion (или другую аналогичную таблицу) с использованием в качестве идентификатора значение функции LAST_INSERT_ID().
3. Вставка в order_item аналогично п.2.

А как себя эта схема поведет при многопользовательском режиме и одновременной вставке? LAST_INSERT_ID() возвращает значение для текущего сеанса или глобальное?
« Последнее редактирование: 21-07-2011 15:35 от Kivals » Записан
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #7 : 21-07-2011 15:36 » 

Добавлено через 1 минуту:
А как себя эта схема поведет при многопользовательском режиме и одновременной вставке? LAST_INSERT_ID() возвращает значение для текущего сеанса или глобальное?

Да, это безопасно. Это последнее значение auto_increment, сгенерированное в рамках сессии.
« Последнее редактирование: 21-07-2011 18:47 от RXL » Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
duke333
Новенький

it
Offline Offline

« Ответ #8 : 21-07-2011 18:28 » 

т.е. last_insert_id уникален только для определенной таблицы ?

Добавлено через 15 минут и 15 секунд:
да пожалуй вариант  RXL - это самое оптимальное решение для уникального ID для несколькох таблиц
« Последнее редактирование: 21-07-2011 18:43 от duke333 » Записан
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #9 : 21-07-2011 18:50 » 

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

Добавлено через 1 минуту и 49 секунд:
Твой исходный вариант тоже жизнеспособен, если его подрихтовать. HandKot в первом ответе тебе уже показал запрос. Надо только в таблице индексы переделать и поле типа сократить до разумных пределов (см. тип ENUM).
« Последнее редактирование: 21-07-2011 18:53 от RXL » Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
duke333
Новенький

it
Offline Offline

« Ответ #10 : 21-07-2011 19:01 » 

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

Добавлено через 1 минуту и 49 секунд:
Твой исходный вариант тоже жизнеспособен, если его подрихтовать. HandKot в первом ответе тебе уже показал запрос. Надо только в таблице индексы переделать и поле типа сократить до разумных пределов (см. тип ENUM).

а какой из этих двух вариантов более корректный ?

Добавлено через 52 секунды:
и как в вашем варианте будет выглядить первоначальный запрос ?
« Последнее редактирование: 21-07-2011 19:02 от duke333 » Записан
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #11 : 21-07-2011 19:49 » new

Оба. Все зависит от ситуации и вкуса. Надо детально рассмотреть оба варианта (а может и больше), составить запросы к таким базам, проверить необходимость в индексах, время выполнения, расход памяти, нагрузку на СУБД и пр. Параметров может быть много, но в каждом конкретном случае их ценность разная.
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines