Многостоловый запрос MySQL, возвращающий слишком много результатов - PullRequest
1 голос
/ 25 февраля 2011

Мне нужно сделать SELECT в 8 таблицах, но результаты не соответствуют ожиданиям.

Уродливый код:

SELECT equipment.*
FROM equipment
LEFT JOIN equip_adaptador  a ON (a.cod_equip = equipment.cod_equip)
LEFT JOIN equip_antena aa ON (aa.cod_equip = equipment.cod_equip)
LEFT JOIN equip_cable c ON (c.cod_equip = equipment.cod_equip)
LEFT JOIN equip_conector cc ON (cc.cod_equip = equipment.cod_equip)
LEFT JOIN equip_fonte f ON (f.cod_equip = equipment.cod_equip)
LEFT JOIN equip_router r ON (r.cod_equip = equipment.cod_equip)
LEFT JOIN equip_suporte s ON (s.cod_equip = equipment.cod_equip)
WHERE equipment.cod_equip = 'EC726026316A0'

результат - 63 пункта, не верно.

Объясните код выше:

Моя таблица equipment - это моя главная таблица , там у меня есть cod_equip field (главное поле для всех моих подчиненных таблиц).

Все мои подчиненные таблицы Я дал префикс под названием equip_ ( - это всего 7 подчиненных таблиц )

Теперь мне нужно от SELECT до JOIN всех 8 таблиц.

Добавление больше:

Я ожидал 9 строк, но он получил 63 строки, мне нужно показать что-то вроде этого: табличное оборудование (только 1 строка) и другие таблицы, которым он принадлежит.

Например, equip_adaptador был вставлен два раза с одним и тем же cod_equip , тогда мне нужно показать это ..

Этот запрос такой же, как если бы я выполнял один за другим запрос, чтобы посмотреть, что у меня есть с equipment.cod_equip = 'EC726026316A0'

Просто так!

Заранее спасибо людям!

Ответы [ 3 ]

5 голосов
/ 25 февраля 2011

Ваши предложения ON должны иметь ограничения на таблицы, к которым вы присоединяетесь.В настоящее время они этого не делают.Так, например, вы присоединяетесь к equip_fonte во всех случаях, когда equip_adaptador.cod_equip = equipment.cod_equip.И правда этого утверждения не имеет ничего общего с тем, что происходит в equip_fonte.

2 голосов
/ 26 февраля 2011

Происходит следующее: каждая строка, возвращенная из дочерней таблицы, сопоставляется с каждой строкой, возвращенной из других дочерних таблиц.

Как и ожидалось, возвращена одна родительская строка.

Но если одна из дочерних таблиц имеет семь (7) совпадающих строк, а другая дочерняя таблица имеет девять (9) совпадающих строк, вы получите 7 * 9 = 63 возвращенных строк.

Это ожидаемый набор результатов, согласно спецификации SQL.

Вот тестовый пример, который демонстрирует, что происходит:

CREATE TABLE t (id INT);
CREATE TABLE c1 (id INT, t_id INT);
CREATE TABLE c2 (id INT, t_id INT);

INSERT INTO t VALUES (1);
INSERT INTO c1 VALUES (11,1),(12,1);
INSERT INTO c2 VALUES (21,1),(22,1);

SELECT t.id, c1.id AS c1, c2.id AS c2
FROM t
JOIN c1 ON (t.id = c1.t_id)
JOIN c2 ON (t.id = c2.t_id)

id  c1   c2
--  ---  ---
1   11   21
1   12   21
1   11   22
1   12   22

Обратите внимание, что строки из c1 повторяются, один раз для каждой строки из c2. Аналогично для строк из c2.

Это именно тот набор результатов, который мы ожидаем.

Если мы не хотим перекрестного соединения (декартово произведение) дочерних строк, мы можем запустить отдельные запросы:

SELECT t.id, c1.id AS c1
FROM t
JOIN c1 ON (t.id = c1.t_id) 

SELECT t.id, c2.id AS c2
FROM t
JOIN c2 ON (t.id = c2.t_id)

id  c1
--  ---
1   11
1   12

id  c2
--  ---
1   21
1   22

Это один из способов избежать генерации «повторяющихся» дочерних строк.

1 голос
/ 25 февраля 2011

Возможно, имена таблиц в условиях соединения неверны ... Попробуйте это

SELECT equipment.*
    FROM equipment
    LEFT JOIN equip_adaptador  a ON (a.cod_equip = equipment.cod_equip)
    LEFT JOIN equip_antena aa ON (aa.cod_equip = equipment.cod_equip)
    LEFT JOIN equip_cable c ON (c.cod_equip = equipment.cod_equip)
    LEFT JOIN equip_conector cc ON (cc.cod_equip = equipment.cod_equip)
    LEFT JOIN equip_fonte f ON (f.cod_equip = equipment.cod_equip)
    LEFT JOIN equip_router r ON (r.cod_equip = equipment.cod_equip)
    LEFT JOIN equip_suporte s ON (s.cod_equip = equipment.cod_equip)
    WHERE equipment.cod_equip = 'EC726026316A0'
...