赞
踩
1、使用left join比直接使用where速度快
参考:使用left join比直接使用where速度快的原因
多表使用left join只是把主表里的所有数据查询出来,其他表只查询表中的符合条件的某一条记录,所以速度非常快;而多表使用where内联,是把所有表的数据全查出来,然后进行比对,所以速度非常慢。
使用left join要注意确定哪一张表是主表,如果无法确定主表,则选择哪张表查询的字段最多,就把哪张表作为主表。
示例如下:
使用left join,同样的数据量,时间不到1秒钟!
- SELECT a.projectno,MAX(a.projectname) projectname,max(a.projectMoney) projectMoney,
- max(a.projectLimitYear) projectLimitYear,max(a.monthcharge) monthcharge,
- max(c.orgname) orgname,max(d.businesstypename) businesstypename,max(e.name) name,
- max(b.dicvalue) dicvalue,
- min(CONVERT(varchar(100),DATEADD("DAY",jbl.DelayDays,jbl.ReportTime),23)) as period,
- max(f.fiveleveltype) fiveleveltype,max(a.ProjectInfoId) ProjectInfoId,
- max(g.FlowRunId) FlowRunId
- FROM
- (select ProjectInfoId,ProjectNo,Status,OrgId,TypeID,UserAId,IsDelete,ProjectName,ProjectMoney,ProjectLimitYear,MonthCharge from jt_biz_projectinfo) a
- LEFT JOIN
- (select b.* from (select MAX(id) id, ProjectNo from JT_Biz_Lecture group by ProjectNo) a,
- JT_Biz_Lecture b where a.id=b.id) f
- on a.projectno=f.projectno
- LEFT JOIN
- (select DicId,IsDelete,DicValue,DicCode from jt_Base_Dictionary) b
- ON a.status=b.dicId
- LEFT JOIN
- (select ProjectNo,DelayDays,ReportTime from Jt_Biz_LectureTemp) jbl
- ON a.projectno=jbl.projectno
- LEFT JOIN
- (select IsDelete,OrgName,OrgId from jt_base_org) c
- ON a.orgid=c.orgid
- LEFT JOIN
- (select ID,BusinessTypeName from d_businesstype) d
- ON a.typeid=d.id
- LEFT JOIN
- (select UserInfoId,IsDelete,Name,UserName from jt_base_userInfo) e
- ON a.useraid=e.userinfoid
- LEFT JOIN
- (select UserId,PostId,OrgIds from JT_Base_Post_UserOrg) j
- ON j.UserId=e.userinfoid
- LEFT JOIN
- (select PostId from JT_Base_Post) k
- ON j.PostId=k.PostId
- LEFT JOIN
- (select FlowRunId,ProjectId from jt_flow_run) g
- ON a.ProjectInfoId=g.ProjectId
- LEFT JOIN
- (select FlowRunId from JT_Flow_Run_Prcs) h
- ON g.FlowRunId = h.FlowRunId
- LEFT JOIN
- (select OrgId,OrgName from JT_Base_Org) l
- ON a.OrgId=l.OrgId
- WHERE a.status in(82,83,84) and a.isdelete=0
- and b.isdelete=0 and c.isdelete=0 and e.isdelete=0
- and (l.OrgId in(null) or e.UserName='chenqf') group by a.ProjectNo;
- 不使用left join,同样数据量,时间大概在50秒的样子!
- select a.projectno,max(a.projectname) projectname,max(a.projectMoney) projectMoney,
- max(a.projectLimitYear) projectLimitYear,max(a.monthcharge) monthcharge,
- max(c.orgname) orgname,max(d.businesstypename) businesstypename,max(e.name) name,
- max(b.dicvalue) dicvalue,
- min(CONVERT(varchar(100),DATEADD("DAY",jbl.DelayDays,jbl.ReportTime),23)) as period,
- max(f.fiveleveltype) fiveleveltype,max(a.ProjectInfoId) ProjectInfoId,
- max(g.FlowRunId) FlowRunId
- from (select DicId,IsDelete,DicValue,DicCode from jt_Base_Dictionary) b,
- (select IsDelete,OrgName,OrgId from jt_base_org) c,
- (select UserInfoId,IsDelete,Name,UserName from jt_base_userInfo) e,
- (select ID,BusinessTypeName from d_businesstype) d,
- (select FlowRunId,ProjectId from jt_flow_run) g,
- (select FlowRunId from JT_Flow_Run_Prcs) h,
- (select UserId,PostId,OrgIds from JT_Base_Post_UserOrg) j,
- (select PostId from JT_Base_Post) k,
- (select OrgId,OrgName from JT_Base_Org) l,
- (select ProjectNo,DelayDays,ReportTime from Jt_Biz_LectureTemp) jbl,
- (select ProjectInfoId,ProjectNo,Status,OrgId,TypeID,UserAId,IsDelete,ProjectName,ProjectMoney,ProjectLimitYear,MonthCharge from jt_biz_projectinfo) a
- left join
- (select b.* from (select MAX(id) id, ProjectNo from JT_Biz_Lecture group by ProjectNo) a,
- JT_Biz_Lecture b where a.id=b.id) f
- on a.projectno=f.projectno where a.status=b.dicId and a.status in(82,83,84)
- and a.projectno=jbl.projectno and a.orgid=c.orgid and a.typeid=d.id
- and a.useraid=e.userinfoid and j.UserId=e.userinfoid and a.isdelete=0
- and b.isdelete=0 and c.isdelete=0 and e.isdelete=0 and g.FlowRunId = h.FlowRunId
- and (l.OrgId in(null) or e.UserName='chenqf')
- group by a.ProjectNo;
2、LEFT JOIN关联表中ON,WHERE后面跟条件的区别
写SQL本想通过 A left join B on and 后面的条件来使查出的两条记录变成一条,奈何发现还是有两条。
后来发现 on and 不会过滤结果记录条数,只会根据and后的条件是否显示 B表的记录,A表的记录一定会显示。
不管and 后面的是A.id=1还是B.id=1,都显示出A表中所有的记录,并关联显示B中对应A表中id为1的记录或者B表中id为1的记录。
运行sql : select * from student s left join class c on s.classId=c.id order by s.id
运行sql : select * from student s left join class c on s.classId=c.id and s.name="张三" order by s.id
运行sql : select * from student s left join class c on s.classId=c.id and c.name="三年级三班" order by s.id
通过查询相关资料了解到:
数据库在通过连接两张或多张表来返回记录时,都会生成一张中间的临时表,然后再将这张临时表返回给用户。
在使用left jion时,on和where条件的区别如下:
1、 on条件是在生成临时表时使用的条件,它不管on中的条件是否为真,都会返回左边表中的记录。
2、where条件是在临时表生成好后,再对临时表进行过滤的条件。这时已经没有left join的含义(必须返回左边表的记录)了,条件不为真的就全部过滤掉。
假设有两张表:
表1:tab1
表2:tab2
两条SQL:
1、select * form tab1 left join tab2 on (tab1.size = tab2.size) where tab2.name=’AAA’
2、select * form tab1 left join tab2 on (tab1.size = tab2.size and tab2.name=’AAA’)
其实以上结果的关键原因就是left join,right join,full join的特殊性,不管on上的条件是否为真都会返回left或right表中的记录,full则具有left和right的特性的并集。 而inner jion没这个特殊性,则条件放在on中和where中,返回的结果集是相同的。
3、Where条件中使用主表条件过滤速度较快
-
- SELECT
- *
- FROM
- USER_BORROW T1 -- 数据量2~3万条
- LEFT JOIN USER T3 ON T3.OID_USER_ID = T1.OID_USER_ID
- LEFT JOIN USER_DETAIL T4 ON T4.OID_USER_ID = T1.OID_USER_ID
- LEFT JOIN USER_ARCHIVES T5 ON T5.OID_ARCHIVE_ID = T1.OID_ARCHIVE_ID -- USER_ARCHIVES数据量2~3万条
- LEFT JOIN PRODUCT_MST T6 ON T6.OID_PROD_ID = T5.OID_PROD_ID
- LEFT JOIN TENANT T7 ON T7.OID_TENANT_ID = T5.OID_TENANT_ID
- LEFT JOIN TENANT T8 ON T8.OID_TENANT_ID = T5.OID_TENANT_XS_ID
- LEFT JOIN (
- SELECT
- OID_BORROW_ID,
- SUM(REPAY_AMOUNT_TOTAL) AS FEE_AMOUNT
- FROM
- USER_POUNDAGE_REPAY
- WHERE
- REPAY_FLG = '0'
- GROUP BY
- OID_BORROW_ID
- ) T9 ON T1.BORROW_ID = T9.OID_BORROW_ID
- WHERE
- 1 = 1
- -- 此处使用T1.OID_TENANT_ID进行数据过滤查询速度很快,
- -- 但是使用T5.OID_TENANT_ID进行过滤数据查询速度极慢,不确定是否跟T1为主表有关系???
- AND T1.OID_TENANT_ID IN (
- SELECT
- OT.OID_TENANT_ID
- FROM
- DEPARTMENT_USER DU
- INNER JOIN OPERATOR_TENANT OT ON OT.OID_OPERATOR_USER_ID = DU.OID_ADMIN_USER_ID
- WHERE
- DU.DEL_FLG = '0'
- AND DU.OID_DEPARTMENT_ID = (
- SELECT
- DU1.OID_DEPARTMENT_ID
- FROM
- DEPARTMENT_USER DU1
- WHERE
- DU1.OID_ADMIN_USER_ID = ?
- AND DU1.DEL_FLG = '0'
- )
- )
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。