Запрос при отношении многие ко многим

Alexos

Новичок
Запрос при отношении многие ко многим

К примеру, у меня есть 3 MySQL-таблицы с отношением многие ко многим:
1. Таблица разделов каталога table_razdel -> id_r|name_razdel
2. Таблица товаров table_tovari -> id_t|name_tovar
3. И таблица table_links связей между 1-й и 2-й таблицей -> id_r|id_t

Задача такая..

Мне нужно выбрать айди разделов при name_razdel равным, например, "Унитазы", а также не связанные с товаром $_GET['id_t'].
Как это выполнить одним запросом?
А то я сделал сначала один запрос, потом в цикле ещё один подзапрос, и сдается мне, что это не есть гут.
Вот как это у меня:

PHP:
$query = 'SELECT id_r FROM table_razdel WHERE name = 'Унитазы';

$result = $db->query($query);

while($row = $db->fetch_array($result)) {

     if (!$db->num_rows($db->query('SELECT * FROM table_links WHERE id_r = '.$row['id_r'].
                              ' AND id_t = '.$_GET['id_t']))) {

          // ... различные действия

     
     } // if

} // while
ИМХО как то через задний проход... :(
 

Romantik

TeaM PHPClub
1. Почему бы товары не хранить как
id_t|id_r|name_tovar ?
2. AND id_t = '.$_GET['id_t']
отвратительное решение!!!
нужно так:
PHP:
$id_t= intval($_GET['id_t']);
if($id_t)>0){
...
}
 

Alexos

Новичок
1. Почему бы товары не хранить как
id_t|id_r|name_tovar ?
Потому что один товар может принадлежать разным разделам.
Romantik, ответьте, пожалуйста, если знаете, все же на мой вопрос.
 

Евгений Ищенко

Guest
select tr.id_r from table_razdel tr, table_tovari tt, table_links tl
where tr.name_razdel = 'Унитаз'
and tr.id_r in (select tl.id_r from tl where tl.id_t != 'ваша переменная id_t' )

Кажись так
 

Alexos

Новичок
Евгений Ищенко
Я думаю, что исходя из задания:
Мне нужно выбрать айди разделов при name_razdel равным, например, "Унитазы", а также не связанные с товаром $_GET['id_t'].
правильнее все же так:
[sql]SELECT tr.id_r FROM table_razdel tr, table_links tl
WHERE tr.name_razdel = 'Унитаз'
AND tr.id_r NOT IN (SELECT tl.id_r FROM tl WHERE tl.id_t = 'моя переменная id_t')[/sql]

Однако, извините за невнимательность, я забыл сказать в начале топика, что у меня MySQL, к сожалению, старше 4-й версии и не поддерживает вложенные запросы :(

Вопрос остается открытым. Подскажите, пожалуйста, возможно ли выполнить эту задачу в один запрос, используя MySQL, не поддерживающую вложенные запросы?
 

Евгений Ищенко

Guest
Alexos
Это одно и то же. просто вы вынесли not перед вложенным запросом, а я поместил внутрь т.к. если в списке выданном подзапросом будет NULL, то отработает не правильно (в oracle по крайней мере).

-~{}~ 19.01.05 10:48:

Не совсем понял:
Автор оригинала: Alexos
что у меня MySQL, к сожалению, старше 4-й версии и не поддерживает вложенные запросы :(
Здесь http://dev.mysql.com/doc/mysql/en/Subqueries.html


Starting with MySQL 4.1, all subquery forms and operations that the SQL standard requires are supported, as well as a few features that are MySQL-specific. With MySQL versions prior to 4.1, it was necessary to work around or avoid the use of subqueries. In many cases, subqueries can successfully be rewritten using joins and other methods
написано что с 4.1 поддерживаются подзапросы.
или я вас не правильно понял.
 

kvf77

Red Devil
SELECT * FROM razdel, links, tovar WHERE razdel.razdel_id = 'унитаз' AND links.razdel_id = razdel.razdel_id AND links.tovar_id = tovar.tovar_id
Вот и все

-~{}~ 19.01.05 13:06:

Если у тебя ID - это не текстовая строка, а уникальный номер раздела, то еще проще можно:
SELECT * FROM links, tovar WHERE links.razdel_id = $ID AND tovar.tovar_id = links.tovar_id
 

Alexos

Новичок
Евгений Ищенко
Старше, я имел ввиду старее :) А именно Version 3.23.58
Так что не покатит. Как сделать запрос используя вложенный подзапрос, я знаю. Мне интересно можно ли сделать без него.

kvf77
не то :(

Есть ещё варианты?
 

TuBu

Guest
что-то такое:

[sql]
select tr.id_r, sum(if(tt.id_t='ваша переменная id_t', 1, 0)) as c from table_razdel tr inner join table_links tl using(id_r) left join table_tovar tt on tl.id_t=tt.id_t where tr.name_razdel = 'Унитаз' group by tr.id_r having c = 0;
[/sql]

-~{}~ 20.01.05 00:10:

А если надо выбирать и те разделы, у которых нет товаров, то первый джойн тоде левый (LEFT):

[sql]
SELECT tr.id_r, sum(
IF (
tt.id_t = 'ваша переменная id_t', 1, 0
) ) AS c
FROM table_razdel tr
LEFT JOIN table_links tl
USING ( id_r )
LEFT JOIN table_tovar tt ON tl.id_t = tt.id_t
WHERE tr.name_razdel = 'Унитаз'
GROUP BY tr.id_r
HAVING c = 0;
[/sql]

-~{}~ 20.01.05 00:10:

Ну, вообщем, разберетесь
 
Сверху