一个复杂的SQL分析

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

导出手动添加的人脉分析

前提分析

先看用到的表:

connections_batch_relation: 批量添加人脉表

connections_company_initialization: 公司初始化任务表

connections_my_relation: 我的人脉表

connections_task_data: 数据处理任务表

user: 用户信息表

winlabel_company: 企业信息表

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

然后进行sql查询:

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起来的

第一个子查询

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

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

sql 复制代码
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中,然后来看第一个子查询:

sql 复制代码
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、添加人脉企业、类型、添加时间

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

第二个子查询

sql 复制代码
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表中操作,返回想要的字段

相关推荐
代码欢乐豆1 分钟前
NoSQL——期末复习(5)第五章Neo4J重点思考题
数据库·nosql·neo4j
IT猫咪酱2 分钟前
【sql】CAST(GROUP_CONCAT())实现一对多对象json输出
数据库·sql·json
Heavydrink22 分钟前
Jdbc笔记02
java·笔记
Lzehui1 小时前
Mybatis的set标签,动态SQL
java·sql·mybatis
m0_748255261 小时前
the request was rejected because no multipart boundary was found
java
一二小选手1 小时前
【Nginx】Nginx代理模式相关概念解释及Nginx安装
java·nginx·代理模式
建爱永恒1 小时前
数据库工程师进阶秘籍:云计算基础知识题目精选与答案(附PDF)
数据库·安全·云计算·数据库系统
罗不丢1 小时前
小组作业协同介绍
数据库·项目管理·大作业·项目协同·小组作业
Ahern_1 小时前
Oracle 数据库使用SPM固定执行计划
数据库·sql·oracle
猿java1 小时前
字节2面:为了性能,你会违反数据库三范式吗?
java·mysql·面试