Reputation: 490
How would I impose a left join limit on query with multiple left joins that depend on one another? See comment below on the LIMIT:
SELECT
a.*,GROUP_CONCAT(c.body SEPARATOR ' ') AS bodies
FROM a
LEFT JOIN b ON b.id_a=a.id
LEFT JOIN c ON c.id=b.id_c LIMIT 5 # LIMIT 5 Here Does Not Work
WHERE ...
Sample data set...
DROP TABLE IF EXISTS `a`;
CREATE TABLE `a` (
`id` int(11) NOT NULL
);
-- Contains relationship between a and c
DROP TABLE IF EXISTS `b`;
CREATE TABLE `b` (
`id_a` int(11) NOT NULL,
`id_c` int(11) NOT NULL
);
-- Contains body contents
DROP TABLE IF EXISTS `c`;
CREATE TABLE `c` (
`id` int(11) NOT NULL,
`body` varchar(2000) NOT NULL
);
-- ----------------------------
-- Sample Records
-- ----------------------------
INSERT INTO `a` VALUES ('1');
INSERT INTO `b` VALUES
('1','1'), ('1','2'), ('1','3'),
('1','4'), ('1','5'), ('1','6'),
('1','7'), ('1','8'), ('1','9'),
('1','10');
INSERT INTO `c` VALUES
('1','aa'),('2','bb'), ('3','cc'),
('4','dd'), ('5','ee'), ('6','ff'),
('7','gg'), ('8','hh'), ('9','ii'),
('10','jj');
... and SQLFiddle at http://sqlfiddle.com/#!9/c1822/12
Also here is a subquery rewrite that I tried but doesn't work because the outer table is not accessible from the nested subquery and fails with "unknown column a.id in where clause": http://sqlfiddle.com/#!9/c1822/3
Also here is a subquery find_in_set rewrite http://sqlfiddle.com/#!9/2d43bb/1 which works but is too slow with large data sets.
Upvotes: 1
Views: 1433
Reputation: 1270391
Here is a proper way to write this using variables. Andomar's solution might work, but it suffers three issues:
order by
needs to be in a subquery.select
. So, you should not assign a variable in one expression and use it in another.So, a better version looks like:
select . . .
from table1 t1 left join
(select t2.*,
(@rn := if(@id = t2.t1_id, @rn + 1,
if(@id := t2.t1_id, 1, 1)
)
) as rn
from (select t2.*
table2 t2
order by t1_id
) t2 cross join
(select @rn := 0, @id := -1) params
) t2
on t2.t1_id = t1.id
where t2.rn <= 5; -- At most 5 rows
Your use of group_concat()
suggests that a group by
is also necessary. However, your question seems more general about limiting the rows and you don't provide much information on what you are actually trying to accomplish.
Upvotes: 0
Reputation: 238176
You can use variables to number each row in the subquery. Then you can filter out rows based on that number. This example limits the left join
to at most 3 results with the same t1_id
:
select *
from table1 t1
left join
(
select @rn := case when t1_id = @prev_id then @rn + 1 else 1 end rn
, @prev_id := t1_id
, t2.*
from table2 t2
order by
t1_id
) t2rn
on t2rn.t1_id = t1.id
and t2rn.rn < 4 -- At most 3 rows
Upvotes: 2