mysql多表联合查询,加条件筛选,需要排序分页,要求不使用join连接,要如何实现?

新手上路,请多包涵

问题背景:

  • 有a、b、c三个表,a跟b、c都是一对多的关系,a有自增主键a.id,这是排序分页的依据,但按BOSS要求,不许在b、c表中添加a.id的冗余字段(包括外键手段,外键是使用的a中另一个保证唯一的定长字符串a.guid);
  • b、c表中均有字段用于作筛选条件,且由于a跟b、c都是一对多的关系,无法在a表中添加b、c表的筛选用字段作冗余;
  • 说是由于预计数据量会非常大(百万级),不允许使用join连接,且由于考虑以后迁移其他数据库的可能性,不允许使用自增主键id做外键,包括不允许使用自增主键id作为其他表的冗余字段。

需求:

  • 获取a表数据列表,分页显示,排序依据是a.id;
  • 有必选的筛选条件,在a表中,在此举例为a.set;
  • 有可选的筛选条件,条件分别在b、c表中,在此举例为b.type,c.name。

探索(此问题未解决,求助各位大佬帮忙):

  • 此问题的等价join连接SQL语句如下所示:

    SELECT a.id,a.guid,a.col1,a.col2 
    FROM a 
        INNER JOIN b ON a.guid = b.a_guid
        INNER JOIN c ON a.guid = c.a_guid
    WHERE a.set = 'xxx'          -- 必选条件
        AND b.type = 1           -- 整数,可选筛选条件
        AND c.name LIKE '%XXX%'  -- 模糊查询,可选筛选条件
    GROUP BY a.guid              -- 去重
    ORDER BY a.id                -- 按a.id排序
    LIMIT 0,10                   -- 分页
    ;
  • 不允许使用join连接,故思路自然是添加冗余字段,问题背景也说明了a表无法添加b、c表的冗余字段,故在b、c表中都添加了a_set(即a.set)的冗余字段;
  • 若不考虑分页,仅根据单独的可选筛选条件自然可以先筛选出a.guid,如根据b.type筛选:

    SELECT b.a_guid FROM b WHERE b.a_set = 'xxx' AND b.type = 1 GROUP BY b.a_guid;
  • 但这样问题自然在于b表中没有a.id字段可供排序,无法进行分页,分页思路自然是上面的语句查询出b.a_guid的结果集后,在a表中使用IN进行查询,然后按a.id进行排序分页,但此思路又有个问题是本身a、b、c三表的数据量预计就会很大,筛选出的b.a_guid的结果集可能也会非常大,可能会导致SQL语句超出长度限制,即便增加了SQL语句的长度限制或者使用子查询的方法,但IN中的数据量太多的话,不也是会很影响查询效率吗,会不会效率还不如使用JOIN连接?
  • 就此,思路卡在此处,实在想不出好的解决方案,在此求助路过的大神帮忙,提供一下解决的思路
阅读 17k
2 个回答

不想有冗余字段,那就建个关联表,把a b 表的数据关联起来,想排序就加个a.id,索引建起来。

最好不要用IN,In的效率比较低。很多时候JOIN的效率反而更高的,你用到JOIN了已经涉及到多表了,关系型数据库,干的就是关系,擅长的就是查询;百万级,其实ok的;就是控制一下join的表数,关联越多效率就越低。

根据你的业务来设计数据库,业务体现数据未来可能的增长方向。可以先批量撸数据进去然后测一下sql效率看看。

解决了吗?老哥

我在工作中也遇到了类似的问题,不过公司没限制使用join,但是我平时自己做项目习惯在代码中手动关联;然而这个情况 我也没想到有啥好办法解决

希望老哥分享下

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏