Модераторы: skyboy

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> MySQL: Связывание двух таблиц по надобности 
:(
    Опции темы
krinart
Дата 5.3.2010, 11:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 75
Регистрация: 10.4.2008
Где: Донецк

Репутация: нет
Всего: нет



Всем доброго дня. Сначала написал это сообщение в раздел Mysql, но там чтото тихо, решил продублировать сюда.


Есть таблицы
Код

CREATE TABLE `tours` (
`tourID` bigint( 20 ) unsigned NOT NULL AUTO_INCREMENT ,
`type` tinyint( 3 ) unsigned NOT NULL,
PRIMARY KEY ( `tourID` ) ,
)

CREATE TABLE `tour_hotel` (
`tour_hotel_ID` bigint( 20 ) unsigned NOT NULL AUTO_INCREMENT ,
`tourID` bigint( 20 ) unsigned NOT NULL ,
`hotelID` bigint( 20 ) unsigned NOT NULL ,
`hotelOrder` tinyint( 3 ) unsigned NOT NULL ,
`param` varchar( 17 ) COLLATE utf8_unicode_ci NOT NULL ,
PRIMARY KEY ( `tour_hotel_ID` ) ,
) 


Смысл в том, что есть таблица туры(tours), в которой хранится информация о турах(даты, цена и т.д.), есть таблица tour_hotel, в которой связываются туры и отели, в которых проживают люди. Это сделано для того, чтобы с одним туром могло быть связано несколько отелей. В таблице tours есть поле type, в котором хранится количесто отелей, связанных с этим туром, на практике оно бывает равно либо 1, либо 2. Поле hotelOrder показывает, в каком порядке происходит проживание в отелях в каждом туре(1, 2 и т.д.). В таблице tour_hotel есть информация о проживании в отеле, для примера я сделал одно поле param.

Например, это может выглядеть так

tours
|----------|---------|
| tourID |   type  |
|----------|---------|
|      1     |     2     |
|----------|---------|
то есть у тура 2 отеля


tour_hotel
|--------------------|-----------|--------------|--------------------|----------------|
| tour_hotel_ID |   tourID |   hotelID  |    hotelOrder    |    param     |
|--------------------|-----------|--------------|--------------------|----------------|
|             1           |       1      |        10      |            1            |       123       |
|--------------------|-----------|--------------|--------------------|----------------|
|             2           |       1      |        20      |            2            |       123       |
|--------------------|-----------|--------------|--------------------|----------------|
соответсвенно, с первым туром связаны два отеля, у которых указана очередность  проживания и некий параметр


Таблицу hotels не привожу, так как в её структуре ничего интересного нет.

Теперь, собственно, вопрос. Как мне сделать связывание таблицы tours с таблицей tour_hotel, если hotel.type=2, два раза?

Например, есть такой запрос
Код

SELECT * FROM tours t INNER JOIN tour_hotel th ON t.tourID=th.tourID
WHERE th.hotelOrder=1 AND th.param=123



Но мне нужно, чтобы этому параметру соответстовали и остальные отели в этом туре. Я придумал способ, по котому я ВСЕГДА сравниваю два отеля, подставляя для второго в условие по th.hotelOrder количество отелей в туре, то есть либо ещё раз первый, либо, как и требуется, второй
Код

SELECT * FROM (tours t INNER JOIN tour_hotel th1 ON t.tourID=th1.tourID) INNER JOIN tour_hotel th2 ON t.tourID=th2.tourID
WHERE th1.hotelOrder=1 AND th2.hotelOrder=t.type AND th1.param=123  AND th2.param=123 


Но понятно, что это не самый оптимальный способ, особенно если учесть, что туров будет хранится несколько миллионов(!). А выбирать сначала первые отели, а потом циклом перебирать все остальные в этому туре - тоже не хочется. Посоветуйте, а?






PM MAIL ICQ   Вверх
Akina
Дата 5.3.2010, 11:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Советчик
****


Профиль
Группа: Модератор
Сообщений: 20581
Регистрация: 8.4.2004
Где: Зеленоград

Репутация: 45
Всего: 454



Цитата(krinart @  5.3.2010,  12:29 Найти цитируемый пост)
В таблице tours есть поле type, в котором хранится количесто отелей, связанных с этим туром, на практике оно бывает равно либо 1, либо 2.

Переопределённые данные. Удалить.

Цитата(krinart @  5.3.2010,  12:29 Найти цитируемый пост)
Как мне сделать связывание таблицы tours с таблицей tour_hotel, если hotel.type=2, два раза?

А это ЗАЧЕМ? при связывании ты получишь в наборе ровно столько записей, сколько отелей связано с туром.


--------------------
 О(б)суждение моих действий - в соответствующей теме, пожалуйста. Или в РМ. И высшая инстанция - Администрация форума.

PM MAIL WWW ICQ Jabber   Вверх
krinart
Дата 5.3.2010, 11:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 75
Регистрация: 10.4.2008
Где: Донецк

Репутация: нет
Всего: нет



Akina, Потому что мне нужно находить информацию не об одном туре, а к примеру, о 10

Код

LIMIT 0, 10


При обычном связывании я получу не 10 туров, а 10 связок тур-отель. Поэтому мне необходимо сделать так, чтобы каждому туру соответствовала одна строка в результирующем запросе


Цитата(Akina @  5.3.2010,  11:38 Найти цитируемый пост)
Переопределённые данные. Удалить.

Это поле пока что вспомогательное, пусть будет. Если обойдусь без него - удалю

PM MAIL ICQ   Вверх
Akina
Дата 5.3.2010, 22:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Советчик
****


Профиль
Группа: Модератор
Сообщений: 20581
Регистрация: 8.4.2004
Где: Зеленоград

Репутация: 45
Всего: 454



Цитата(krinart @  5.3.2010,  12:56 Найти цитируемый пост)
Потому что мне нужно находить информацию не об одном туре, а к примеру, о 10

Ну и находи, какие проблемы?

Цитата(krinart @  5.3.2010,  12:56 Найти цитируемый пост)
При обычном связывании я получу не 10 туров, а 10 связок тур-отель.

Так и должно быть.

Цитата(krinart @  5.3.2010,  12:56 Найти цитируемый пост)
мне необходимо сделать так, чтобы каждому туру соответствовала одна строка в результирующем запросе

А вот так НЕ должно быть, если их может быть несколько. Следует использовать уровни группировки на стадии отображения результата на клиенте.

Цитата(krinart @  5.3.2010,  12:56 Найти цитируемый пост)
Это поле пока что вспомогательное, пусть будет. Если обойдусь без него - удалю

То есть использовать гнруппировку и Count религия явно не позволяет... ну и ладно.


--------------------
 О(б)суждение моих действий - в соответствующей теме, пожалуйста. Или в РМ. И высшая инстанция - Администрация форума.

PM MAIL WWW ICQ Jabber   Вверх
krinart
Дата 10.3.2010, 14:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 75
Регистрация: 10.4.2008
Где: Донецк

Репутация: нет
Всего: нет



Прошу прощение за долгое молчание.


Цитата(Akina @  5.3.2010,  22:33 Найти цитируемый пост)
Ну и находи, какие проблемы?

Проблема в том, что сначала мне нужно найти ВСЕ туры, которые попадают под данный критерий, чтобы вывести пользователю сообщение типа "всего найдено Х туров".
А потом уже найти LIMIT x,y туров, в зависимости от того, на какой странице пользователь. Так вот как мне ОДНИМ запросом узнать общее количество подходящих туров. Конечно, можна сначала получить туры, где критерию соответствует первый отель, а потом в цикле проверять все оставшиеся отели. Но, как я написал выше, эту операцию придётся проделать дважды, а по-моему это не есть гут.

Цитата(Akina @  5.3.2010,  22:33 Найти цитируемый пост)
Следует использовать уровни группировки на стадии отображения результата на клиенте.

Если можна подробнее?

Цитата(Akina @  5.3.2010,  22:33 Найти цитируемый пост)
религия явно не позволяет... ну и ладно.

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


PM MAIL ICQ   Вверх
Fortop
Дата 10.3.2010, 14:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2200
Регистрация: 13.11.2007
Где: Донецк

Репутация: 2
Всего: 42



SQL_CALC_FOUND_ROWS в запросе

и второй запрос сразу после него 
Код

SELECT FOUND_ROWS()





--------------------
Мир это Я.
Живее всех живых.
PM MAIL   Вверх
krinart
Дата 10.3.2010, 15:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 75
Регистрация: 10.4.2008
Где: Донецк

Репутация: нет
Всего: нет



Fortop,  спасибо, вкусная штучка. Обязательно поиграюсь с ней.

Но основной вопрос был в том, как одним запросом проверить соответствие всех отелей, которые соответствуют каждому туру? Учитывая, что это количество может меняться от тура к туру. Вот как это сделать? Как сделать столько связок(и, соответственно, проверок)в запросе, сколько соответствующих полей в таблице tour_hotel?
PM MAIL ICQ   Вверх
Fortop
Дата 10.3.2010, 15:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2200
Регистрация: 13.11.2007
Где: Донецк

Репутация: 2
Всего: 42



Цитата(krinart @  10.3.2010,  14:07 Найти цитируемый пост)
как одним запросом проверить соответствие всех отелей, которые соответствуют каждому туру?

Судя по коду в 1м сообщении именно это и делается.

В чем вопрос? Как задать в условии несколько разных туров?
Код

WHERE tourID IN (1,2,..., 3453)


Это сообщение отредактировал(а) Fortop - 10.3.2010, 15:42


--------------------
Мир это Я.
Живее всех живых.
PM MAIL   Вверх
krinart
Дата 10.3.2010, 16:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 75
Регистрация: 10.4.2008
Где: Донецк

Репутация: нет
Всего: нет



Fortop, 
В первом сообщении есть два варианта проверки. В первом варианте проверяется только 1 отель на соответствие критерию поиска. Во втором варианте проверяется два, но совсем не красивым способом, хотя по сути и рабочим.  А если будет не два, а три отеля, хотя на практике такое врядли будет. Я хочу на будущее узнать, есть ли возможность средствами SQL связывать две таблицы столько раз для проверки данных, сколько всего существует этих связей. И вернуть значение tourID только в том случае, если все записи соответствуют этому критерию
PM MAIL ICQ   Вверх
Akina
Дата 10.3.2010, 17:09 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Советчик
****


Профиль
Группа: Модератор
Сообщений: 20581
Регистрация: 8.4.2004
Где: Зеленоград

Репутация: 45
Всего: 454



Цитата(krinart @  10.3.2010,  17:36 Найти цитируемый пост)
есть ли возможность средствами SQL связывать две таблицы столько раз для проверки данных, сколько всего существует этих связей. И вернуть значение tourID только в том случае, если все записи соответствуют этому критерию 

Да, есть. Причём можно реализовать не только динамическое изменение количества связываний, но и даже (о ужас! адепты SQL счас перевернутся в гробу) динамическое изменение структуры результата (количества полей).
Но было бы гораздо проще, если бы ты не старался всё-таки получать информацию ОДНОЙ ЗАПИСЬЮ.



--------------------
 О(б)суждение моих действий - в соответствующей теме, пожалуйста. Или в РМ. И высшая инстанция - Администрация форума.

PM MAIL WWW ICQ Jabber   Вверх
krinart
Дата 10.3.2010, 17:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 75
Регистрация: 10.4.2008
Где: Донецк

Репутация: нет
Всего: нет



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

Я уже понял, что поле tours.type явно лишнее, хотя я об этом и подозревал. Но хотелось бы увидеть ещё какой-нибудь вариант решения моей задачи, я думал, для этого и существуют форумы.
PM MAIL ICQ   Вверх
Fortop
Дата 10.3.2010, 17:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2200
Регистрация: 13.11.2007
Где: Донецк

Репутация: 2
Всего: 42



Цитата(krinart @  10.3.2010,  16:27 Найти цитируемый пост)
я думал, для этого и существуют форумы. 

не надо заблуждаться http://phpclub.ru/faq/WhyForum

Цитата(krinart @  10.3.2010,  16:27 Найти цитируемый пост)
Но хотелось бы увидеть ещё какой-нибудь вариант решения моей задачи

Вы не ответили на мой ответ?
На вопросы вполне правильно и корректно ответил Akina
А где собственно задача? 



--------------------
Мир это Я.
Живее всех живых.
PM MAIL   Вверх
Akina
Дата 10.3.2010, 17:55 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Советчик
****


Профиль
Группа: Модератор
Сообщений: 20581
Регистрация: 8.4.2004
Где: Зеленоград

Репутация: 45
Всего: 454



Просить совета и предложить свой вариант решения - это два взаимоисключающих мероприятия.

Цитата(krinart @  10.3.2010,  18:27 Найти цитируемый пост)
показать, как это сделать следовало бы - адептам SQL, наверное, не с руки

Для этого следует как минимум начать всё сначала. Потому как я, например, уже не въезжаю в эту кашу. Например:

Цитата(krinart @  10.3.2010,  15:00 Найти цитируемый пост)
мне нужно найти ВСЕ туры, которые попадают под данный критерий, чтобы вывести пользователю сообщение типа "всего найдено Х туров".
А потом уже найти LIMIT x,y туров, в зависимости от того, на какой странице пользователь. Так вот как мне ОДНИМ запросом узнать общее количество подходящих туров. Конечно, можна сначала получить туры, где критерию соответствует первый отель, а потом в цикле проверять все оставшиеся отели. 

Так критерий - тура? отеля? обоих сразу? Какие они вообще есть - критерии? Какая она вообще - задача? а не конкретный маленький этапчик?

Цитата(krinart @  5.3.2010,  12:29 Найти цитируемый пост)
Поле hotelOrder показывает, в каком порядке происходит проживание в отелях в каждом туре(1, 2 и т.д.)

То есть на самом деле у клиента нет выбора? 

А вообще что это - отели? Есть тур... селим в первый, кончились места - во второй? или, может, полтура проводим в первом, потом переезжаем во второй?

Какая вообще предметная область? над чем работаем? А то леса не видать - одни деревья.



--------------------
 О(б)суждение моих действий - в соответствующей теме, пожалуйста. Или в РМ. И высшая инстанция - Администрация форума.

PM MAIL WWW ICQ Jabber   Вверх
krinart
Дата 10.3.2010, 18:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 75
Регистрация: 10.4.2008
Где: Донецк

Репутация: нет
Всего: нет



Fortop, я и пытаюсь найти ответ, и поверьте, за время, прошедшее с момента написания первого сообщения,  я пробовал применять полученную здесь информацию на практике.


Цитата(Akina @  10.3.2010,  17:55 Найти цитируемый пост)
Какая вообще предметная область? над чем работаем? А то леса не видать - одни деревья.

Предметная область - система автоматизации подбора туров для туристического агенства. Конечно, и в таблице tours и в таблице tour_hotel намного больше полей, просто сейчас их можно не рассматривать. Если я разберусь, как сделать поиск по одному из них, мне не составит труда дописать и всё остальное.


Цитата(Akina @  10.3.2010,  17:55 Найти цитируемый пост)
Так критерий - тура? отеля? обоих сразу? Какие они вообще есть - критерии? Какая она вообще - задача? а не конкретный маленький этапчик?

Критерий - поле param в таблице tour_hotel. С количеством мест вообще не надо ничего придумывать. В отеле места либо есть, либо нету. Для этого есть отдельное поле в таблице tour_hotel. Но сейчас это не нужно.

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

Если я напишу код
Код

SELECT * FROM tours t INNER JOIN tour_hotel th ON t.tourID=th.tourID
WHERE th.param=2
GROUP BY t.tourID

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


Цитата(Akina @  10.3.2010,  17:55 Найти цитируемый пост)
То есть на самом деле у клиента нет выбора? 

Нет, туры формируются заранее тур-операторами. Точно также, как нельзя установить свои даты туров. Можно лишь выбрать из довольно большого количества уже готовых туров, как я писал в первом сообщении, туров будет порядка 2 миллионов.


Цитата(Akina @  10.3.2010,  17:09 Найти цитируемый пост)
Но было бы гораздо проще, если бы ты не старался всё-таки получать информацию ОДНОЙ ЗАПИСЬЮ.

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


Если максимально упростить вопрос, то он будет звучать примерно так:
Есть две таблицы, связанные отношением один-ко-многим. Пусть в первой таблице только одно поле a. Во второй таблице два поля: a и b. Необходимо найти такие a, у которых все значения b попадают под некий критерий. Как это сделать? И как посчитать количество таких строк в таблице a ?
PM MAIL ICQ   Вверх
Fortop
Дата 10.3.2010, 18:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2200
Регистрация: 13.11.2007
Где: Донецк

Репутация: 2
Всего: 42



Цитата(krinart @  10.3.2010,  17:36 Найти цитируемый пост)
То есть мне нужно найти такие туры, в котором все отели позволяют разместить двух человек.

А в честь чего все? Это при поиске отдельным чекбоксом устанавливается или как?
Откуда такое требование? (впрочем можно и его выполнить) 



--------------------
Мир это Я.
Живее всех живых.
PM MAIL   Вверх
Ответ в темуСоздание новой темы Создание опроса
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Составление SQL-запросов | Следующая тема »


 




[ Время генерации скрипта: 0.0595 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.