专栏名称: 芋道源码
纯 Java 源码分享公众号,目前有「Dubbo」「SpringCloud」「Java 并发」「RocketMQ」「Sharding-JDBC」「MyCAT」「Elastic-Job」「SkyWalking」「Spring」等等
目录
相关文章推荐
芋道源码  ·  Nginx 实现动态封禁IP,详细教程来了 ·  2 天前  
芋道源码  ·  SpringBoot 实现 License ... ·  3 天前  
Java编程精选  ·  Stream流式编程,让代码变优雅 ·  5 天前  
芋道源码  ·  简化本地Feign调用,这样封装真香! ·  4 天前  
51好读  ›  专栏  ›  芋道源码

一个复杂的SQL分析

芋道源码  · 公众号  · Java  · 2024-12-26 09:33

主要观点总结

文章介绍了一个社群和开源项目,并详细解释了一个复杂的SQL查询,该查询用于获取特定用户的人脉数据。文章还提到了基于Spring Boot + MyBatis Plus + Vue & Element的后台管理系统和用户小程序,并邀请读者加入其知识星球。

关键观点总结

关键观点1: 介绍社群和开源项目

提供了相关资源链接

关键观点2: 复杂的SQL查询

详细解释了查询的逻辑和结构,包括多个子查询和表的联接,目的是获取特定用户的人脉数据

关键观点3: 后台管理系统和用户小程序

该系统基于Spring Boot + MyBatis Plus + Vue & Element实现,支持RBAC动态权限、多租户、数据权限、工作流等功能

关键观点4: 两个子查询的解释

第一个子查询从数据处理任务表中获取人脉数据,第二个子查询从我的人脉表中获取数据。这两个查询的结果通过UNION合并。

关键观点5: 邀请加入知识星球

提供了相关的学习资源和内容


正文

👉 这是一个或许对你有用的社群

🐱 一对一交流/面试小册/简历优化/求职解惑,欢迎加入芋道快速开发平台知识星球。下面是星球提供的部分资料: 

👉这是一个或许对你有用的开源项目

国产 Star 破 10w+ 的开源项目,前端包括管理后台 + 微信小程序,后端支持单体和微服务架构。

功能涵盖 RBAC 权限、SaaS 多租户、数据权限、商城、支付、工作流、大屏报表、微信公众号、CRM 等等功能:

  • Boot 仓库:https://gitee.com/zhijiantianya/ruoyi-vue-pro
  • Cloud 仓库:https://gitee.com/zhijiantianya/yudao-cloud
  • 视频教程:https://doc.iocoder.cn
【国内首批】支持 JDK 21 + SpringBoot 3.2.2、JDK 8 + Spring Boot 2.7.18 双版本 

来源:juejin.cn/post/
7352100456334606346


今天公司导出数据用到了一个看着非常复杂的Sql,正好来分析一下

导出手动添加的人脉分析

前提分析

先看用到的表:

  • connections_batch_relation: 批量添加人脉表
  • connections_company_initialization: 公司初始化任务表
  • connections_my_relation: 我的人脉表
  • connections_task_data: 数据处理任务表
  • user: 用户信息表
  • winlabel_company: 企业信息表

然后将公司初始化任务表中的uid(主账号用户id)都取出来,作为下面sql中@abc变量的值

然后进行sql查询:

 SET @abc = '200001720,200000161,200000348,200000162,200001986,200000164,200002219,200001983,200000651,200000808,200002217,200000328,200000809,200001774,200002582,200001850,200002631,200002337,200002516,200000493,200000293,200002163,200001772,200002720,200002718,200002733,200002736,200002740,200002753,200002819,200000890,200002834,200002825,200002039,200000423,200002734,200002964,200002985,200002677,200002998,200002975,200002480,200001992,200003070,200001854,200003172,200003178,200002010,200003217,200002465,200001721,200002777,200003257,200003159,200003326,200003398,200003365,200002021,200003491,200003573,200003580,200003465,200003409,200003622,200000789,200003633,200001758,200001532,200003660,200002986,200003675,200003677,200003679,200002935,200003705,200003712,200003715,200001745,200003787,200003825,200001497,200003884,200003912,200003919,200003982,200003983,200003994,200004002,200004019,200004048,200004063,200004082,200003724,200004098,200004101,200004148,200004020,200004247,200004294,200004295,200004300,200003768,200002026,200004440,200004406,200004450,200004463,200004506,200004530,200004697,200004470,200001786,200001870,200004498,200002603,200004532,200004727,200003619,200004852,200002896,200004872,200001755,200004720,200002147,200004928,200004369,200004935,200004936,200002595,200002342,200004972,200004989,200004990,200004994,200005006';
 
 -- SELECT DISTINCT temp2.pid FROM (
 
 SELECT
 IF(temp.`企业名称` is not null,temp.`企业名称`, (SELECT company_name FROM connections_company_initialization WHERE user_id IN (SELECT IF(parent_id = 0,id,parent_id) as 'pid' FROM `user` WHERE id = temp.uid))) AS '企业名称',
 (SELECT IF(parent_id = 0,id,parent_id) as 'pid' FROM `user` WHERE id = temp.uid) as 'pid',
 
 NULL AS '数量',
 
 temp.`uid`,
 temp.`添加人脉企业`,
 temp.`类型`,
 temp.`添加时间`,
 (
 SELECT EXISTS
 ( SELECT * FROM connections_my_relation WHERE user_id = temp.uid AND company_name = temp.`添加人脉企业` )) AS '是否删除' ,
 (SELECT phone FROM `user` WHERE id = temp.uid) as '手机号',
 (SELECT contact_name FROM `user` WHERE id = temp.uid) as '姓名',
 (SELECT CASE
 WHEN user_comment is null THEN
 ''
 WHEN user_comment = 0 THEN
 '过期用户'
 WHEN user_comment = 1 THEN
 '新用户'
 WHEN user_comment = 2 THEN
 '内部用户'
 WHEN user_comment = 3 THEN
 '试用账户'
 WHEN user_comment = 4 THEN
 '成交会员'
 END AS userComment
 FROM `user` WHERE id = temp.uid) as '用户备注',
 (SELECT w.company_name FROM `user` u LEFT JOIN winlabel_company w ON u.company_id = w.id WHERE u.id = temp.uid) as '用户注册公司名称'
 
 FROM
 (
 SELECT
 null AS '企业名称',
 tt2.user_id AS 'uid',
 tt1.`name` AS '添加人脉企业',
 (SELECT company_type FROM connections_my_relation mr WHERE mr.user_id = tt2.user_id AND mr.company_name = tt1.`name`AS '类型',
 tt1.create_time AS '添加时间'
 FROM
 (
 SELECT
 `name`,
 batch_id,
 user_id,
 create_time
 FROM
 connections_task_data
 WHERE
 join_type = 2
 AND user_id IN (SELECT id FROM `user` WHERE deleted = 0 AND (FIND_IN_SET(id,@abc) OR FIND_IN_SET(parent_id,@abc)))
 ) tt1
 LEFT JOIN connections_batch_relation tt2 ON tt1.batch_id = tt2.batch_id
 
 
 UNION
 SELECT
 null AS '企业名称',
 user_id AS 'uid',
 company_name AS '添加人脉企业',
 company_type AS '类型',
 create_time AS '添加时间'
 FROM
 connections_my_relation
 WHERE
 user_id IN (SELECT id FROM `user` WHERE deleted = 0 AND (FIND_IN_SET(id,@abc) OR FIND_IN_SET(parent_id,@abc)))
 AND batch_id != '预制数据'
 AND CONCAT( company_name, user_id ) NOT IN
 
 (
 SELECT
 CONCAT(tt1.`name`,tt2.user_id)
 FROM
 (
 SELECT
 `name`,
 batch_id,
 user_id,
 create_time
 FROM
 connections_task_data
 WHERE
 join_type = 2
 AND user_id IN (SELECT id FROM `user` WHERE deleted = 0 AND (FIND_IN_SET(id,@abc) OR FIND_IN_SET(parent_id,@abc)))
 ) tt1
 LEFT JOIN connections_batch_relation tt2 ON tt1.batch_id = tt2.batch_id
 )
 ) temp
 
 WHERE temp.`添加时间` >= '2024-02-19 00:00:00'
 
 ORDER BY '企业名称' ASC
 
 -- ) temp2 ORDER BY temp2.pid

先将结果折叠看一下整体的语句,不难发现是对temp表的一次查询

所以sql的整体框架是从temp表中查询

temp是什么:展开折叠发现是由两个子查询UNION起来的

基于 Spring Boot + MyBatis Plus + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能

  • 项目地址:https://github.com/YunaiV/ruoyi-vue-pro
  • 视频教程:https://doc.iocoder.cn/video/

第一个子查询

第一个子查询是对tt1和tt2表的查询,其中tt1又是一个子查询、tt2是批量添加人脉表,所以先看tt1

第一个子查询的子查询(tt1):

SELECT
    `name`,
    batch_id,
    user_id,
    create_time 
FROM
    connections_task_data 
WHERE
    join_type = 2 
    AND user_id IN (
    SELECT
        id 
    FROM
        `user` 
    WHERE
        deleted = 0 
        AND (
            FIND_IN_SET( id, @abc ) 
        OR FIND_IN_SET( parent_id, @abc ))) 
) tt1

从数据处理任务表中查询公司名称、批次id、主账号uid、创建时间,限制条件:不展示直接人脉数据的、主账号uid必须是未删除并且uid或者父uid在上面的给出的id中,然后来看第一个子查询:

SELECT NULL AS
    '企业名称',
    tt2.user_id AS 'uid',
    tt1.`name` AS '添加人脉企业',
    ( SELECT company_type FROM connections_my_relation mr WHERE mr.user_id = tt2.user_id AND mr.company_name = tt1.`name` ) AS '类型',
    tt1.create_time AS '添加时间' 
FROM
    (
    SELECT
        `name`,
        batch_id,
        user_id,
        create_time 
    FROM
        connections_task_data 
    WHERE
        join_type = 2 
        AND user_id IN (
        SELECT
            id 
        FROM
            `user` 
        WHERE
            deleted = 0 
            AND (
                FIND_IN_SET( id, @abc ) 
            OR FIND_IN_SET( parent_id, @abc ))) 
    ) tt1
    LEFT JOIN connections_batch_relation tt2 ON tt1.batch_id = tt2.batch_id

第一个子查询主要是对tt1表中的数据封装,连接tt2表做为补充,封装的字段是企业名称、uid、添加人脉企业、类型、添加时间

所以第一个子查询大概意思是从数据处理任务表中找到对应用户的人脉数据

基于 Spring Cloud Alibaba + Gateway + Nacos + RocketMQ + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能

  • 项目地址:https://github.com/YunaiV/yudao-cloud
  • 视频教程:https://doc.iocoder.cn/video/

第二个子查询

SELECT NULL AS
    '企业名称',
    user_id AS 'uid',
    company_name AS '添加人脉企业',
    company_type AS '类型',
    create_time AS '添加时间' 
FROM
    connections_my_relation 
WHERE
    user_id IN (
    SELECT
        id 
    FROM
        `user` 
    WHERE
        deleted = 0 
        AND (
            FIND_IN_SET( id, @abc ) 
        OR FIND_IN_SET( parent_id, @abc ))) 
    AND batch_id != '预制数据' 
    AND CONCAT( company_name, user_id ) NOT IN (
    SELECT
        CONCAT( tt1.`name`, tt2.user_id ) 
    FROM
        (
        SELECT
            `name`,
            batch_id,
            user_id,
            create_time 
        FROM
            connections_task_data 
        WHERE
            join_type = 2 
            AND user_id IN (
            SELECT
                id 
            FROM
                `user` 
            WHERE
                deleted = 0 
                AND (
                    FIND_IN_SET( id, @abc ) 
                OR FIND_IN_SET( parent_id, @abc )))  
        ) tt1
        LEFT JOIN connections_batch_relation tt2 ON tt1.batch_id = tt2.batch_id 

意思是从我的人脉表中查询uid、添加的人脉企业、类型人脉公司类型、添加时间、同样限制主账号uid必须是未删除并且uid或者父uid在上面的给出的id中,并且批次id不能为预制数据,并且uid和添加的人脉企业组成的唯一不能出现在数据处理任务表中这些不展示直接人脉数据和对应的uid中,同样最后和批量添加人脉表通过批次id联合起来来辅助

两个子查询的字段都相同,所以UNION的结果是将它们合并成一个结果集,自动去除重复的数据

所以temp的临时表就是(运行结果):

最后外面的一层查询就相当于在temp表中操作,返回想要的字段


欢迎加入我的知识星球,全面提升技术能力。

👉 加入方式,长按”或“扫描”下方二维码噢

星球的内容包括:项目实战、面试招聘、源码解析、学习路线。

文章有帮助的话,在看,转发吧。

谢谢支持哟 (*^__^*)