⭐⭐⭐ Spring Boot 项目实战 ⭐⭐⭐ Spring Cloud 项目实战
《Dubbo 实现原理与源码解析 —— 精品合集》 《Netty 实现原理与源码解析 —— 精品合集》
《Spring 实现原理与源码解析 —— 精品合集》 《MyBatis 实现原理与源码解析 —— 精品合集》
《Spring MVC 实现原理与源码解析 —— 精品合集》 《数据库实体设计合集》
《Spring Boot 实现原理与源码解析 —— 精品合集》 《Java 面试题 + Java 学习指南》

摘要: 原创出处 juejin.cn/post/7352100456334606346 「CoderLiz」欢迎转载,保留摘要,谢谢!


🙂🙂🙂关注微信公众号:【芋道源码】有福利:

  1. RocketMQ / MyCAT / Sharding-JDBC 所有源码分析文章列表
  2. RocketMQ / MyCAT / Sharding-JDBC 中文注释源码 GitHub 地址
  3. 您对于源码的疑问每条留言都将得到认真回复。甚至不知道如何读源码也可以请教噢。
  4. 新的源码解析文章实时收到通知。每周更新一篇左右。
  5. 认真的源码交流微信群。

今天公司导出数据用到了一个看着非常复杂的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起来的

第一个子查询

第一个子查询是对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、添加人脉企业、类型、添加时间

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

第二个子查询

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. 1. 前提分析
  2. 2. 第一个子查询
  3. 3. 第二个子查询