Как при запросе по нескольким таблицам получить 1 результат сразу

bovkun

Новичок
Как при запросе по нескольким таблицам получить 1 результат сразу

TABLE 1

magazin_name | gorod_id | rayon_id
--------------------------------------
Имя_1 | 1 | 2
Имя_2 | 1 | 3
Имя_3 | 1 | 2
Имя_4 | 2 | 1


TABLE 2

gorod_id | gorod_name
--------------------------------------
1 | Город_1
2 | Город_2


TABLE 3

gorod_id | rayon_id | rayon_name
--------------------------------------
1 | 1 | Район_1_1
1 | 2 | Район_1_2
1 | 3 | Район_1_3
2 | 1 | Район_2_1
2 | 2 | Район_2_2
2 | 3 | Район_2_3




НУЖЕН РЕЗУЛЬТАТ ВЫБОРКИ

magazin_name | gorod_name | rayon_name
--------------------------------------
Имя_1 | Город_1 | Район_1_2
Имя_2 | Город_1 | Район_1_3
Имя_3 | Город_1 | Район_1_2
Имя_4 | Город_2 | Район_2_1



Я сейчас получаю желаемую картину, но в результате многочисленных запросов. Сначала делаю SELECT по таблице 1, а потом по каждой позиции (город и район) еще по разу прохожу чтобы подставить их наименование. Записей за раз нужно обрабатывать сотнями и полей больше чем в этом примере... Понимаю, что так можно, но вижу, что это как-то не рационально!

Вопрос. Можно (нужно) ли все это объединить в один запрос?

Я перебрал кучу вариантов с JOIN, но все не то. Появляются дубликаты с путаницей в колонках в разных вариация :/
Пример мучений:

Код:
SELECT
    t1.magazin_name, 
    t2.gorod_name,
    t3.rayon_name
FROM
    t1
    INNER JOIN t2 
        ON (t1.gorod_id = t2.gorod_id)
    INNER JOIN t3
        ON (t1.rayon_id = t3.rayon_id);
 

bovkun

Новичок
Автор оригинала: dimagolov
сделай rayon_id в t3 уникальным полем
Я бы рад, так поезд уже ушел. В свое время перемудрил... Структуру таблиц изменить практически не реально. Сайт действующий и сделать такие изменения малой кровью не выйдет.
 

c0dex

web.dev 2002-...
Команда форума
Партнер клуба
Что-то вроде как-то так:

Код:
SELECT straight_join t1.magazin_name, t2.gorod_name, t3.rayon_name
FROM t1
JOIN t3 ON ( t1.rayon_id = t3.rayon_id AND t1.gorod_id = t3.gorod_id )
JOIN t2 ON ( t1.gorod_id = t2.gorod_id )
GROUP BY t1.magazin_name
ORDER BY `t1`.`magazin_name` ASC
LIMIT 0 , 30
 

dimagolov

Новичок
c0dex, у него дурацкая структура таблиц. поверь, что составной ключ по району у него получился по незнанию и толку особого в нем нету.
Кроме того, там GROUP BY у тебя лишний, если пары gorod_id/rayon_id образуют уникальный ключ. Его, кстати, как и другие ключи, а т.ч. внешние, нужно сделать.

bovkun, не говори глупости. у тебя что, rayon_id в код прошиты, или еще что? все, что нужно, так это сделать обновление таблицы районов и таблиц, на нее ссылающихся. через временное поле в t3 это можно сделать за пару-тройку запросов.

-~{}~ 31.01.10 10:48:

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

c0dex

web.dev 2002-...
Команда форума
Партнер клуба
dimagolov
Ну он сказал, что ключей нету, потому я написал как есть. Группировка там не лишняя, так как иначе в данных условиях отбирается неверный rayon_name для последнего 4 ряда, там вместо Район_2_1 будет Район_1_1.

PS: Но эксплейн без force index все равно даже с ключами у меня вышел дебильный.

Имхо надо что-то делать со структурой таблиц >.<
 

dimagolov

Новичок
так как иначе в данных условиях отбирается неверный rayon_name для последнего 4 ряда, там вместо Район_2_1 будет Район_1_1.
это еще почему? и даже если это так, то чем может помочь группировка?
 

c0dex

web.dev 2002-...
Команда форума
Партнер клуба
dimagolov
Запрос автора отбирает данные так:
Код:
magazin_name 	gorod_name 	rayon_name
Имя_4	Город_2	Район_1_1
Имя_1	Город_1	Район_1_2
Имя_3	Город_1	Район_1_2
Имя_2	Город_1	Район_1_3
Имя_4	Город_2	Район_2_1
Имя_1	Город_1	Район_2_2
Имя_3	Город_1	Район_2_2
Имя_2	Город_1	Район_2_3
Запрос вида:

Код:
SELECT t1.magazin_name, t2.gorod_name, t3.rayon_name
FROM t1
INNER JOIN t2 ON ( t1.gorod_id = t2.gorod_id )
INNER JOIN t3 ON ( t1.rayon_id = t3.rayon_id )
GROUP BY t1.magazin_name
LIMIT 0 , 30
Выберет:
Код:
magazin_name 	gorod_name 	rayon_name
Имя_1	Город_1	Район_1_2
Имя_2	Город_1	Район_1_3
Имя_3	Город_1	Район_1_2
Имя_4	Город_2	Район_1_1
-~{}~ 31.01.10 20:51:

А потому как 4 строка по мнению автора должна выглядеть как

Имя_4 | Город_2 | Район_2_1

я предложил вариант свой.
 

dimagolov

Новичок
c0dex, не тупи. ты написал правильный запрос первый раз, там group by был лишний.
Код:
SELECT straight_join t1.magazin_name, t2.gorod_name, t3.rayon_name
FROM t1
INNER JOIN t3 ON ( t1.rayon_id = t3.rayon_id AND t1.gorod_id = t3.gorod_id )
INNER JOIN t2 ON ( t1.gorod_id = t2.gorod_id )
ORDER BY `t1`.`magazin_name` ASC
LIMIT 0 , 30
 

c0dex

web.dev 2002-...
Команда форума
Партнер клуба
да( я забыл, что добавил условие после AND, хотя тут что есть группировка, что нет - ни на что не влияет в данном случае

-~{}~ 31.01.10 23:12:

bovkun
эм, не понял
 

bovkun

Новичок
dimagolov , в первом варианте даже без group by

Код:
SELECT straight_join t1.magazin_name, t2.gorod_name, t3.rayon_name
FROM t1
JOIN t3 ON ( t1.rayon_id = t3.rayon_id AND t1.gorod_id = t3.gorod_id )
JOIN t2 ON ( t1.gorod_id = t2.gorod_id )
0 row(s) returned

---

c0dex Во втором случае результат:

Код:
Имя_4 | Город_2 | Район_2_1
Имя_4 | Город_2 | Район_2_2
Имя_4 | Город_2 | Район_2_3
 

c0dex

web.dev 2002-...
Команда форума
Партнер клуба
bovkun
В первом случае у меня отбираются 4 записи, в соответствии с теми данными, что ты привел в 1 посте. Почему у тебя ноль не знаю.

Есть еще мысли переписать на derived query, с постепенным сужением круга результатов, но выйдет или нет - это уже завтра.
 
Сверху