mysql多重左连接限制

6za6bjd0  于 2021-06-21  发布在  Mysql
关注(0)|答案(2)|浏览(307)

如果查询中有多个相互依赖的左连接,如何对其施加左连接限制?请参见下面关于限制的评论:

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 ...

示例数据集。。。

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');

... 和摆弄http://sqlfiddle.com/#!2012年9月18日
还有一个我尝试过的子查询重写,但没有成功,因为外部表无法从嵌套子查询访问,并且由于“where子句中的未知列a.id”而失败:http://sqlfiddle.com/#!9/c1822/3号
这里还有一个子查询find\ in\ u set rewritehttp://sqlfiddle.com/#!9/2d43bb/1,工作正常,但对于大数据集来说太慢。

ercv8c1e

ercv8c1e1#

下面是一个使用变量编写的正确方法。安德奥马尔的解决方案或许可行,但它面临三个问题:
在mysql的最新版本中 order by 需要在子查询中。
更重要的是,mysql不能保证 select . 因此,不应该在一个表达式中指定变量,而在另一个表达式中使用它。
变量未在查询中初始化
因此,更好的版本如下所示:

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

你使用 group_concat() 表明 group by 也是必要的。然而,关于限制行的问题似乎更为笼统,对于实际要完成的任务,您并没有提供太多信息。

vuktfyat

vuktfyat2#

可以使用变量对子查询中的每一行进行编号。然后可以根据该数字筛选出行。这个例子限制了 left join 最多3个相同的结果 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

例如sql fiddle。

相关问题