一个复杂的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表中操作,返回想要的字段

相关推荐
roman_日积跬步-终至千里8 小时前
【Java 并发-面试】从线程基础到企业级开发的知识点概况
java·开发语言
m0_748233178 小时前
C与C++:底层编程的六大核心共性
java·开发语言
u0109272718 小时前
使用Scrapy框架构建分布式爬虫
jvm·数据库·python
坊钰9 小时前
【Rabbit MQ】Rabbit MQ 介绍
java·rabbitmq
l1t9 小时前
DeekSeek辅助总结PostgreSQL Mistakes and How to Avoid Them 的一个例子
数据库·postgresql
雀啼春9 小时前
Java中的数据类型
java
醉风塘9 小时前
JDBC批量操作终极指南:PreparedStatement批处理与事务性能优化实战
数据库·性能优化
2401_838472519 小时前
使用Python处理计算机图形学(PIL/Pillow)
jvm·数据库·python
80530单词突击赢9 小时前
C++关联容器深度解析:set/map全攻略
java·数据结构·算法