Как вы делаете много-много табличных внешних объединений?
У меня есть 3 таблицы, foo, foo2bar и bar. foo2bar - это карта многих ко многим между foo и bar. Вот содержимое.
select * from foo
+------+
| fid |
+------+
| 1 |
| 2 |
| 3 |
| 4 |
+------+
select * from foo2bar
+------+------+
| fid | bid |
+------+------+
| 1 | 1 |
| 1 | 2 |
| 2 | 1 |
| 2 | 3 |
| 4 | 4 |
+------+------+
select * from bar
+------+-------+------+
| bid | value | zid |
+------+-------+------+
| 1 | 2 | 10 |
| 2 | 4 | 20 |
| 3 | 8 | 30 |
| 4 | 42 | 30 |
+------+-------+------+
То, что я хочу запросить: "Дайте мне список всех фид и значений с зидом 30"
Я ожидаю ответа на все фиды, поэтому результат будет выглядеть так:
+------+--------+
| fid | value |
+------+--------+
| 1 | null |
| 2 | 8 |
| 3 | null |
| 4 | 42 |
+------+--------+
5 ответов
SELECT * FROM foo
LEFT OUTER JOIN (foo2bar JOIN bar ON (foo2bar.bid = bar.bid AND zid = 30))
USING (fid);
Проверено на MySQL 5.0.51.
Это не подзапрос, он использует круглые скобки, чтобы указать приоритет соединений.
SELECT * FROM
foo LEFT JOIN
(
Foo2bar JOIN bar
ON foo2bar.bid = bar.bid AND zid = 30
)
ON foo.fid = foo2bar.fid;
непроверенной
Работая, вы можете начать с вашего выбора. Не включайте столбцы, которые вы не хотите видеть в конечном итоге.
SELECT foo.fid, bar.value
Затем мы можем выполнить предложение WHERE, которое можно увидеть так, как вы его выразили.
SELECT foo.fid, bar.value
WHERE bar.zid = 30
Теперь самое сложное - соединить вещи вместе для нашего предложения FROM, используя LEFT JOINs, потому что мы хотим видеть каждый fid, независимо от того, существуют ли промежуточные совпадения:
SELECT foo.fid, bar.value
FROM foo
LEFT JOIN foo2bar ON foo.fid = foo2bar.fid
LEFT JOIN bar ON foo2bar.bid = bar.bid
WHERE bar.zid = 30
OR bar.zid IS NULL
Если вы не вернете строку для fid = 3, значит ваш сервер не работает.
Этот код должен делать то, что я думаю, что вы хотите:
SELECT
F.fid,
SQ.value
FROM
dbo.Foo F
LEFT OUTER JOIN
(
SELECT F2B.fid, B.value
FROM dbo.Bar B
INNER JOIN dbo.Foo2Bar F2B ON F2B.bid = B.bid WHERE B.zid = 30
) SQ ON SQ.fid = F.fid
Имейте в виду, что можно получить два значения для фида, если оно связано с двумя барами с зидом 30.
Кстати, вопрос на самом деле не в отношении многих ко многим: это можно сделать просто как союз.
Реальное "многие ко многим" в SQL - это CROSS JOIN