数据库复杂sql如何编写入手

前言:说到数据库我想大家都不陌生,对主流的数据库都会基本使用,但是要写好sql完成复杂的sql编写是需要对数据库原理,sql脚本语法有一定的了解的,但是对于开发人员来说,平常都是在curd写一些业务代码,数据库接触的也不是那么复杂,对于复杂的业务场景,面对sql显然束手无策,对于后端开发人员来说去看一个几百行,几千行的sql实在头大,

出现这种sql的业务场景:

1,数据库多实例跨库查询,数据不同步,无法实现,主从同步实现。

2,数据库业务比较老,产品从多少年迭代过来的,发展成那种能不动就不动的业务代码或者sql.

3,业务本身就复杂,没有选择互联网产品,比如做一些数据分析,数据统计,你不采用大数据,一是成本高,企业成本也是有预算。

4,复杂的业务,比如金融,电商,需要做业务清算的都比较复杂。

5,多端的业务统计汇总,整个系统的业务统计。

以上几种情况都会出现业务负责,涉及到数据库统计计算的时候其实都是很复杂的,我们对于业务的发展没有好的规划和排期就会导致这样的问题发生,业务的复杂度不应该在数据存储上面,显然出现这样的情况只有一种原因,那就是设计不够量化,设计不够到位,没有一个闭环的业务,设计不够好,不能完全实现拓展和移植。

小杨今天就教大家如何写好一个复杂的sql,首先小杨数据库其实不算很精,但是对于一些复杂的sql我也是束手无策,但是呢你学习了程序,是有逻辑思想,所以你要通过排除和分析,对比,逆向思维去思考这个问题,分析这个问题的本质,当然了这个是身经百战才能有的能力,只有经过了大项目的压力,抗住了太多的压力才能不慌不忙去分析和解决问题。

今天就来分享一下小杨写这种复杂的sql如何写:

我们现在有个跨数据库实例的查询,多个库查询,我这边需要统计业务的答题做题数据,比如问卷星的题目和答案,我们通过送权益的方式兑换礼品,当然这是我们售后做满意度调查都会送成长值。当然我们的渠道有app,微信公众号,小程序,消息通知等。我们统计报表客户在哪个渠道答了多少题,分数是多少,答案是多少,我们需要改进的地方和成长值结算,这都是算成本。

显然这俩者完全没有任何关系,你在渠道答题和我问卷题目有啥关系,但是这是业务链路,比较长的链路了,我们可以答完题抽奖送积分。

我们通过任务触发去关联我们答卷的消息,把题目展示出来就行了。

LEFT JOIN (
	SELECT
		MAX( result ) result,
		CARE_TARGET_ID 
	FROM
		(
		SELECT
		CASE
				
			WHEN
				tc.SEND_RESULT LIKE CONCAT( '%', '"code":"200"', '%' ) THEN
					1 ELSE 0 
				END result,
	tt.CARE_TARGET_ID 
FROM
	database.tt_job tt
	LEFT JOIN database.tt_job_channel tc ON tc.`CARE_TARGET_ID` = tt.`CARE_TARGET_ID` 
	) 
GROUP BY
	CARE_TARGET_ID 
	) c1 ON c1.CARE_TARGET_ID = t.`CARE_TARGET_ID`
	LEFT JOIN (
	SELECT
		r1.number,
		r1.`ANSWER_TEXT`,
		r1.`ID`,
		r1.`TITLE`,
		r1.`CARE_TARGET_ID`,
		r1.`persion_id` 
	FROM
		(
		SELECT
			td.`TITLE`,
			ROW_NUMBER ( ) over ( PARTITION BY tp.`PERSION_ID` ORDER BY td.q_index ) AS number,
			td.`ANSWER_TEXT`,
			td.`ID`,
			tt.`CARE_TARGET_ID`,
			tp.`persion_id` 
		FROM
			database.tt_job tt
			LEFT JOIN database.tc_answer tp ON tp.`persion_id` = tt.`ANSWER_ID`
			LEFT JOIN database.tc_answer_detail td ON td.person_id = tp.id 
		WHERE
			td.title != '题目' 
			AND td.answer_text != null
			AND tt.bill_type ='51291006'
		ORDER BY
			td.q_index ASC 
		) r1 
	WHERE
		r1.number = 1 
	) t1 ON t1.CARE_TARGET_ID = t.`CARE_TARGET_ID`
	LEFT JOIN (
	SELECT
		r2.number,
		r2.`ANSWER_TEXT`,
		r2.`ID`,
		r2.`TITLE`,
		r2.`CARE_TARGET_ID`,
		r2.`persion_id` 
	FROM
		(
		SELECT
			td.`TITLE`,
			ROW_NUMBER ( ) over ( PARTITION BY tp.`PERSION_ID` ORDER BY td.q_index ) AS number,
			td.`ANSWER_TEXT`,
			td.`ID`,
			tt.`CARE_TARGET_ID`,
			tp.`persion_id` 
		FROM
			database.tt_job tt
			LEFT JOIN database.tc_answer tp ON tp.`persion_id` = tt.`ANSWER_ID`
			LEFT JOIN database.tc_answer_detail td ON td.person_id = tp.id 
		WHERE
			td.title != '题目' 
			AND td.answer_text != null 
			AND tt.bill_type ='51291006' 
		ORDER BY
			td.q_index ASC 
		) r2 
	WHERE
		r2.number = 2 
	) t2 ON t2.CARE_TARGET_ID = t.`CARE_TARGET_ID`
	LEFT JOIN (
	SELECT
		r3.number,
		r3.`ANSWER_TEXT`,
		r3.`ID`,
		r3.`TITLE`,
		r3.`CARE_TARGET_ID`,
		r3.`persion_id` 
	FROM
		(
		SELECT
			td.`TITLE`,
			ROW_NUMBER ( ) over ( PARTITION BY tp.`PERSION_ID` ORDER BY td.q_index ) AS number,
			td.`ANSWER_TEXT`,
			td.`ID`,
			tt.`CARE_TARGET_ID`,
			tp.`persion_id` 
		FROM
			database.tt_job tt
			LEFT JOIN database.tc_answer tp ON tp.`persion_id` = tt.`ANSWER_ID`
			LEFT JOIN database.tc_answer_detail td ON td.person_id = tp.id 
		WHERE
			td.title != '题目' 
			AND td.answer_text != null
			AND tt.bill_type= '51291006'
		ORDER BY
			td.q_index ASC 
		) r3 
	WHERE
		r3.number = 3 
	) t3 ON t3.CARE_TARGET_ID = t.`CARE_TARGET_ID`
	LEFT JOIN (
	SELECT
		r4.number,
		r4.`ANSWER_TEXT`,
		r4.`ID`,
		r4.`TITLE`,
		r4.`CARE_TARGET_ID`,
		r4.`persion_id` 
	FROM
		(
		SELECT
			td.`TITLE`,
			ROW_NUMBER ( ) over ( PARTITION BY tp.`PERSION_ID` ORDER BY td.q_index ) AS number,
			td.`ANSWER_TEXT`,
			td.`ID`,
			tt.`CARE_TARGET_ID`,
			tp.`persion_id` 
		FROM
			database.tt_job tt
			LEFT JOIN database.tc_answer tp ON tp.`persion_id` = tt.`ANSWER_ID`
			LEFT JOIN database.tc_answer_detail td ON td.person_id = tp.id 
		WHERE
			td.title != '题目' 
			AND td.answer_text != null
			AND tt.bill_type = '51291006' 
		ORDER BY
			td.q_index ASC 
		) r4 
	WHERE
		r4.number = 4 
	) t4 ON t4.CARE_TARGET_ID = t.`CARE_TARGET_ID`
	LEFT JOIN (
	SELECT
		r5.number,
		r5.`ANSWER_TEXT`,
		r5.`ID`,
		r5.`TITLE`,
		r5.`CARE_TARGET_ID`,
		r5.`persion_id` 
	FROM
		(
		SELECT
			td.`TITLE`,
			ROW_NUMBER ( ) over ( PARTITION BY tp.`PERSION_ID` ORDER BY td.q_index ) AS number,
			td.`ANSWER_TEXT`,
			td.`ID`,
			tt.`CARE_TARGET_ID`,
			tp.`persion_id` 
		FROM
			database.tt_job tt
			LEFT JOIN database.tc_answer tp ON tp.`persion_id` = tt.`ANSWER_ID`
			LEFT JOIN database.tc_answer_detail td ON td.person_id = tp.id 
		WHERE
			td.title != '题目' 
			AND td.answer_text != null
			AND tt.bill_type = '51291006'  
		ORDER BY
			td.q_index ASC 
		) r5 
	WHERE
		r5.number = 5 
	) t5 ON t5.CARE_TARGET_ID = t.`CARE_TARGET_ID`
	LEFT JOIN (
	SELECT
		r6.number,
		r6.`ANSWER_TEXT`,
		r6.`ID`,
		r6.`TITLE`,
		r6.`CARE_TARGET_ID`,
		r6.`persion_id` 
	FROM
		(
		SELECT
			td.`TITLE`,
			ROW_NUMBER ( ) over ( PARTITION BY tp.`PERSION_ID` ORDER BY td.q_index ) AS number,
			td.`ANSWER_TEXT`,
			td.`ID`,
			tt.`CARE_TARGET_ID`,
			tp.`persion_id` 
		FROM
			database.tt_job tt
			LEFT JOIN database.tc_answer tp ON tp.`persion_id` = tt.`ANSWER_ID`
			LEFT JOIN database.tc_answer_detail td ON td.person_id = tp.id 
		WHERE
			td.title != '题目' 
			AND td.answer_text != null
			AND tt.bill_type  ='51291006' 
		ORDER BY
			td.q_index ASC 
		) r6 
	WHERE
		r6.number = 6 
	) t6 ON t6.CARE_TARGET_ID = t.`CARE_TARGET_ID`
	LEFT JOIN (
	SELECT
		r7.number,
		r7.`ANSWER_TEXT`,
		r7.`ID`,
		r7.`TITLE`,
		r7.`CARE_TARGET_ID`,
		r7.`persion_id` 
	FROM
		(
		SELECT
			td.`TITLE`,
			ROW_NUMBER ( ) over ( PARTITION BY tp.`PERSION_ID` ORDER BY td.q_index ) AS number,
			td.`ANSWER_TEXT`,
			td.`ID`,
			tt.`CARE_TARGET_ID`,
			tp.`persion_id` 
		FROM
			database.tt_job tt
			LEFT JOIN database.tc_answer tp ON tp.`persion_id` = tt.`ANSWER_ID`
			LEFT JOIN database.tc_answer_detail td ON td.person_id = tp.id 
		WHERE
			td.title != '题目' 
			AND td.answer_text != null
			AND tt.bill_type ='51291006'
		ORDER BY
			td.q_index ASC 
		) r7 
	WHERE
		r7.number = 7 
	) t7 ON t7.CARE_TARGET_ID = t.`CARE_TARGET_ID`
	LEFT JOIN (
	SELECT
		r8.number,
		r8.`ANSWER_TEXT`,
		r8.`ID`,
		r8.`TITLE`,
		r8.`CARE_TARGET_ID`,
		r8.`persion_id` 
	FROM
		(
		SELECT
			td.`TITLE`,
			ROW_NUMBER ( ) over ( PARTITION BY tp.`PERSION_ID` ORDER BY td.q_index ) AS number,
			td.`ANSWER_TEXT`,
			td.`ID`,
			tt.`CARE_TARGET_ID`,
			tp.`persion_id` 
		FROM
			database.tt_job tt
			LEFT JOIN database.tc_answer tp ON tp.`persion_id` = tt.`ANSWER_ID`
			LEFT JOIN database.tc_answer_detail td ON td.person_id = tp.id 
		WHERE
			td.title != '题目' 
			AND td.answer_text != null
			AND tt.bill_type ='51291006' 
		ORDER BY
			td.q_index ASC 
		) r8 
	WHERE
		r8.number = 8 
	) t8 ON t8.CARE_TARGET_ID = t.`CARE_TARGET_ID`
	LEFT JOIN (
	SELECT
		r9.number,
		r9.`ANSWER_TEXT`,
		r9.`ID`,
		r9.`TITLE`,
		r9.`CARE_TARGET_ID`,
		r9.`persion_id` 
	FROM
		(
		SELECT
			td.`TITLE`,
			ROW_NUMBER ( ) over ( PARTITION BY tp.`PERSION_ID` ORDER BY td.q_index ) AS number,
			td.`ANSWER_TEXT`,
			td.`ID`,
			tt.`CARE_TARGET_ID`,
			tp.`persion_id` 
		FROM
			database.tt_job tt
			LEFT JOIN database.tc_answer tp ON tp.`persion_id` = tt.`ANSWER_ID`
			LEFT JOIN database.tc_answer_detail td ON td.person_id = tp.id 
		WHERE
			td.title != '题目' 
			AND td.answer_text != null
			AND tt.bill_type = '51291006' 
		ORDER BY
			td.q_index ASC 
		) r9 
	WHERE
		r9.number = 9 
	) t9 ON t9.CARE_TARGET_ID = t.`CARE_TARGET_ID`
	LEFT JOIN (
	SELECT
		r10.number,
		r10.`ANSWER_TEXT`,
		r10.`ID`,
		r10.`TITLE`,
		r10.`CARE_TARGET_ID`,
		r10.`persion_id` 
	FROM
		(
		SELECT
			td.`TITLE`,
			ROW_NUMBER ( ) over ( PARTITION BY tp.`PERSION_ID` ORDER BY td.q_index ) AS number,
			td.`ANSWER_TEXT`,
			td.`ID`,
			tt.`CARE_TARGET_ID`,
			tp.`persion_id` 
		FROM
			database.tt_job tt
			LEFT JOIN database.tc_answer tp ON tp.`persion_id` = tt.`ANSWER_ID`
			LEFT JOIN database.tc_answer_detail td ON td.person_id = tp.id 
		WHERE
			td.title != '题目' 
			AND td.answer_text !=null
			AND tt.bill_type = '51291006'
		ORDER BY
			td.q_index ASC 
		) r10 
	WHERE
		r10.number = 10 
	) t10 ON t10.CARE_TARGET_ID = t.`CARE_TARGET_ID` 
	AND t.bill_type = '51291006' 
WHERE
	1 = 1 
	AND p.care_type_code = '70851005' 

 扎眼一看这个sql特别长是不是,这只是一部分我不全部展示了,通过分析10个子查询,对应的题目和答案通过函数编号去标记题目信息。

数据库复杂sql如何编写入手_第1张图片

 分层查询,嵌套:

第一层:

	SELECT
			td.`TITLE`,
			ROW_NUMBER ( ) over ( PARTITION BY tp.`PERSION_ID` ORDER BY td.q_index ) AS number,
			td.`ANSWER_TEXT`,
			td.`ID`,
			tt.`CARE_TARGET_ID`,
			tp.`persion_id` 
		FROM
			database.tt_job tt
			LEFT JOIN database.tc_answer tp ON tp.`persion_id` = tt.`ANSWER_ID`
			LEFT JOIN database.tc_answer_detail td ON td.person_id = tp.id 
		WHERE
			td.title != '题目' 
			AND td.answer_text != null 
			AND tt.bill_type = '51291006'
		ORDER BY
			td.q_index ASC 

ROW_NUMBER ( ) over ( PARTITION BY tp.`PERSION_ID` ORDER BY td.q_index ) AS number,

函数根据id分组且下标排序,然后获取到 id排序取指定数据的编号把数据返回

第二层:

SELECT
		r1.number,
		r1.`ANSWER_TEXT`,
		r1.`ID`,
		r1.`TITLE`,
		r1.`CARE_TARGET_ID`,
		r1.`persion_id` 
	FROM
		(

) r1 WHERE
		r1.number = 1

 第二层数据就简单了根据第一层的数据返回的赋值到外层了,显然我们获取指定r1,number的那条数据对不对

第三层:

LEFT JOIN (
) t2 ON t2.CARE_TARGET_ID = t.`CARE_TARGET_ID`

第三层无非就是把第二层的统计数据 返回到外层然后查询主键关联到外面的表,从而完成了一次嵌套子查询。显然这个sql也没有那么难啊。

当然还有4层5层,78层也很正常。

编写复杂sql的内功心法:

1,拆解复杂sql的逻辑业务,从内到外,这点和程序不一样,程序是从上往下,而sql是从内到外。

2,每一层查询分析,直到外层,把数据反出去。

3,合理运用mysql内置函数,帮助我们分析统计。

4,以功能实现为主,优化性能我们可以后期优化。

 ————没有与生俱来的天赋,都是后天的努力拼搏(我是小杨,谢谢你的关注和支持)

你可能感兴趣的:(数据库,数据库,sql)