使用In改进SQL查询减少内部联接

时间:2017-09-18 08:21:52

标签: sql postgresql

我遇到了一些遗留代码,在这些代码中,他们使用了两个内连接,我将其替换为以下内容。

 select p.id
 from publisher p 
    inner join retailer r on p.retailer_id = r.id
 where  p.id IN  (1,4,5 .... around 100 or more random ids I get from code) 
 order by case r.sector_id when r.sector_id then 1 else 2 end,
          p.seo_frontpage_factor asc,
          case (r.poi_sector_id) when r.poi_sector_id then 3 else 4 end,
          p.id asc

以前的查询如下所示。

select p.id
from publisher p 
   inner join retailer r on p.retailer_id = r.id
   inner join (select 1 as id union all select 2 ,union all select 3 ......) as x on p.id = x.id
   order by case r.sector_id when r.sector_id then 1 else 2 end,
           p.seo_frontpage_factor asc,
           case (r.poi_sector_id) when r.poi_sector_id then 3 else 4 end,
           p.id asc

我的问题是,这是一个减少内部联接以提高性能的好主意吗?如果不是我可以做什么来优化这个,或者这很好,因为它是?

1 个答案:

答案 0 :(得分:1)

IN子句比内连接更具可读性。因此,进行此更改以提高可读性是个好主意。优化器应该将两个查询视为相同,如果它有任何好处: - )

该查询显然是为了对其零售商的100多个发布商ID进行排名。仅返回发布商ID是非常罕见的,但是,我们不知道结果当然是做了什么。显然,应用程序只需要零售商排名的ID。

更新:由于joop,我在下一部分中出现了错误,现在已经纠正了。

您可以进一步提高可读性:

case r.sector_id when r.sector_id then 1 else 2 end

就是

case when r.sector_id is null then 2 else 1 end

相同
case (r.poi_sector_id) when r.poi_sector_id then 3 else 4 end

case when r.poi_sector_id is null then 4 else 3 end

一种奇怪的写作方式。甚至可能是一个错误。

CASE表达式在非空值后排序为空,所以我们也可以使用

order by r.sector_id is null, p.seo_frontpage_factor, r.poi_sector_id is null, p.id

因为PostgreSQL在false之前排序true(顺便说一句,与MySQL相同)。