奇怪的SQL问题1
业务上有一个需求:查询一个仓库是否有业务数据?一个仓库里有产品或者各种单据上用到了这个仓库,就说明这个仓库有业务数据,用户不能删除。
项目里采用的是实时查询,因为单据的数据量会越来越大,单据种类有多种,如销售单、采购单等。如果直接select 仓库id from 单据 where 仓库id in (1, 2,3)这种的话会查询这种单据的符合条件的所有记录,其实我只需要在这种单据里找到含有这个仓库的一条记录就行了,没必要找所有记录。于是就有了下面这个sql:
select 仓库id
from dual
where exists(
select 1
from sales_order where `仓库id` = 仓库id
) or exists(
select 1
from purchase_order where `仓库id` = 仓库id
)
union all
select 仓库id2
from dual
where exists(
select 1
from sales_order where `仓库id` = 仓库id2
) or exists(
select 1
from purchase_order where `仓库id` = 仓库id2
)
union all
select 仓库id3
from dual
where exists(
select 1
from sales_order where `仓库id` = 仓库id3
) or exists(
select 1
from purchase_order where `仓库id` = 仓库id3
)
exists 只要找到一条满足条件的记录就返回, 如果第一个exists满足,那么后面的exists就短路了,按理说这种sql写法应该性能很高,但是执行结果显示性能很低。
换成如下:
select 仓库id
from sales_order
where `仓库id` in (仓库id, 仓库id2, 仓库id3)
union
select `仓库id`
from purchase_order
where `仓库id` in (仓库id, 仓库id2, 仓库id3)
这种写法扫描表里所有满足条件的记录并且union 去重,性能竟然是上面写法的10倍。
奇怪的SQL问题 2
项目里用到了复杂的sql分页查询,这个sql多表关联,并且有子查询,sql嵌套了3层, 在对最后的结果集进行order by排序的时候,发现竟然不是稳定排序,在业务上就会造成用户困扰,用户在第一页看到这条数据,翻到第二页的时候,发现还有这条数据。 解决方法就是再对id进行排序。
网友评论