关于SQL 查询效率问题 left join 改成 inner join union

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了关于SQL 查询效率问题 left join 改成 inner join union相关的知识,希望对你有一定的参考价值。

由于 业务需要 查询 是关联 多表 。逻辑 可以 直接 写出 select ... from A left join B on ... left join C on ... left join D on ...
但由于 实际 数据中 B、C 表 使用left join 查询 和 C、D表 使用 left join 查询 速度 极慢 用时 近 30s。
原 语句 查询 全部 数据 近 70s 显示 近2k 条 ,A B C D 每个表数据量 只有 50-200W 条。
将 left join 改成 inner join union 。查询速度 可以 提升 到 3s 内 。但 会导致语句过长 可读性 差。
想问问有没有 更高效 且 语句 可读性 跟好的 方法。
表中 是有 索引的 但是 需要 模糊查询的功能。

参考技术A 你这个三秒是减少了查询结果吧。。 两种查询不是同一个意思。

代码中有这么多联系不好改,
如果少的话用子查询可以提高速度如:
select A.* from A
where A.id in(select B.Aid from B)追问

查询 结果 不一致 。那就无效 了。
你这样写 和Inner join 一个意思 少了 数据

追答

也不是无效,,第二种方式查询结果相当于= 号查询,
第1种,是=外还有部分空值也查询出来了,(表达意思不好。) 你百度一下就知道。。

left right inner 三种形式的连接

追问

我不是问你 inner join 和left join 的区别。

追答

恩 ,是少了数据。。一般都是等价链接吧。。

参考技术B 这是一对矛盾,您就直接用inner join吧,效率会高点。追问

inner join 查询 后 缺少 需要的 数据

追答

FULL JOIN 应该可以

参考技术C 建索引,后就快了。追问

有索引的。

Sql关于两个left join 的问题

接着之前的问过的问题,也就是有三个表,一个库房列表room,一个货柜表hgb,一个商品表spb,已知库房表字段为:
库房名name,货柜表关键字段为所在库房kfname,货柜号hgno,商品表关键字段为所在库房kfname,商品编号spno,现在要统计每个库房多少个货柜,多少个商品,sql语句该怎么写,如果只查每个库房多少个货柜则可以
select a.name,count(b.hgno) from room a left join hgb b on a.name=b.kfname group by a.name

上面这句完全可以,关键还要查商品个数,如果写成:
select a.name,count(b.hgno),count(c.spno) from room a left join hgb b on a.name=b.kfname group by a.name left join spb c on a..name=c.name
查出的结果完全不对,请问高人,该怎么写?
上面那句我写错了,应该是:
select a.name,count(b.hgno),count(c.spno) from room a left join hgb b on a.name=b.kfname left join spb c on a.name=c.name group by a.name
就是这句也是不行的,请高人帮助!

你的错误在于货柜表hgb和商品表spb都是独立与房列表room关联的,而你却要放到一个连接语句中进行统计,这样就潜在的将货柜表hgb和商品表spb关联了
比如数据如下
room:name hgb:name ,hgno spb: name,spno
A A 1 A 1
B A 2 A 2
B 1 B 1
B 2 B 2
正常执行结果是
name count(b.hgno), count(c.spno)
A 2 2
B 2 2

但是按照你的语句是
name count(b.hgno), count(c.spno)
A 4 4
B 4 4
就是因为连续的星型连接造成的

你要实现的功能得这样
select R.name, R.Chg, S.Csp
from
(select a.name name,count(b.hgno) Chg from room a left join hgb b on a.name=b.kfname group by a.name) R,
(select a.name name,count(b.spno) Csp from room a left join spb b on a.name=b.kfname group by a.name) S
where R.name=S.name追问

感谢你的回答,你这个方法是对的,但我想再问下,假设如果我库房里还有其它的也要一起统计,那写法是不是跟你的写法相似,再加多个“(select a......) t”这种之类的呢?谢谢!

追答

嗯,可以用这种方法,因为是不同的分类,所以要在每个分类上统计,再连接

参考技术A 应该是这样才对:
select a.name,count(b.hgno),count(c.spno) from room a left join hgb b on a.name=b.kfname left join spb c on a..name=c.name group by a.name追问

不好意思,我上面写错了,我测试时就是你这样写的,但结果完全不正确,而且查出来的count(b.hgno),count(c.spno)
两个字段是一样的

以上是关于关于SQL 查询效率问题 left join 改成 inner join union的主要内容,如果未能解决你的问题,请参考以下文章

SQL优化:慎用标量子查询,改用left join提升查询效率

关于 LEFT JOIN SQL 查询的 WHERE 帮助

sql inner join 与 left join和right join 执行效率上面有多大差别?

SQL中 LEFT JOIN ON 条件的效率高低比较

SQL开发实战技巧系列:从执行计划看NOT INNOT EXISTS 和 LEFT JOIN效率,记住内外关联条件不要乱放

如何使用 LEFT JOIN 查询将 RAW SQL 转换为 DQL