Рассмотрим ваш запрос:
SELECT b.* FROM a
LEFT JOIN b ON b.word=a.word
WHERE a.id=1
LIMIT 2
-- This sub-query returns the following result:
+-------+------+
| name | word |
+-------+------+
| Peter | xyz |
| John | xyz |
+-------+------+
Если без полного синтаксиса из подзапроса, ваш основной синтаксис будет выглядеть так:
SELECT c.name, first_join.word, c.product FROM first_join
LEFT JOIN c ON c.name=first_join.name;
Давайте заменим c.name, first_join.word, c.product
на *
. Тогда вы получите такой результат:
+-------+------+-------+---------+
| name | word | name | product |
+-------+------+-------+---------+
| Peter | xyz | Peter | blah |
| Peter | xyz | Peter | blah2 |
| Peter | xyz | Peter | blah3 |
| Peter | xyz | Peter | blah4 |
| Peter | xyz | Peter | blah5 |
| Peter | xyz | Peter | blah6 |
| John | xyz | John | hello |
| John | xyz | John | world |
| John | xyz | John | blah |
+-------+------+-------+---------+
Теперь, вот где вы спрашиваете себя, хотите ли вы этого или нет? Если это не так, вам нужно убедиться, что вы понимаете логику того, что вы пытаетесь сделать здесь. Как, например, почему ваш подзапрос first_join
возвращает две строки, а когда вы LEFT JOIN
, он возвращает все строки из table c
?
Ну, ответ на этот вопрос из-за вашего ON c.name=first_join.name
. Он соответствует всем вхождениям Питера и Джона в table c
независимо от ограничения, которое вы наложили в подзапросе. Если вы установите ограничение для внешнего запроса, он также не будет работать.
ТЛ; др
Если вы используете MySQL 8.0, вы можете попробовать этот запрос ниже:
SELECT name,word,product FROM
(SELECT
b.name, b.word,c.product,
ROW_NUMBER() OVER (PARTITION BY c.name ORDER BY c.name DESC) AS wRow
FROM
a JOIN
b ON a.word=b.word JOIN
c ON c.name=b.name
WHERE a.id=1) r
WHERE wRow IN (1,2)
ORDER BY name DESC;
Fiddle
Два других примера:
-- First: by using INNER JOIN and UNION (as suggested in the comment).
SELECT b.name,b.word,r.product FROM a JOIN b ON a.word=b.word JOIN
((SELECT * FROM c WHERE c.name='peter' LIMIT 2) UNION
(SELECT * FROM c WHERE c.name='john' LIMIT 2)) r
ON b.name=r.name
WHERE a.id=1;
-- Second: by using LEFT JOIN.
SELECT b.Name,b.Word,IF(p.product IS NULL,j.product,p.product) AS 'Product'
FROM a JOIN b ON a.word=b.word LEFT JOIN
(SELECT * FROM c WHERE NAME='peter' LIMIT 2) p ON b.name=p.name LEFT JOIN
(SELECT * FROM c WHERE NAME='john' LIMIT 2) j ON b.name=j.name
WHERE a.id=1 AND b.name IN (p.name,j.name);
ОБНОВЛЕНИЕ: ОК. Не красиво, но этот запрос может работать. Я тестировал на MySQL 5.7. ;)
SELECT b.Name,b.Word,c.Product FROM a
JOIN b ON a.word=b.word
JOIN c ON b.name=c.name
JOIN (SELECT c.name,
REPLACE(SUBSTRING_INDEX(GROUP_CONCAT(product SEPARATOR ' '),' ',2),' ',',') prod
FROM c GROUP BY NAME) r
ON b.name=r.name WHERE FIND_IN_SET(c.product,prod);
Но будет гораздо проще, если у вас есть столбец со значением автоинкремента, по крайней мере.