改进SQL查询,减少与中的内部联接

改进SQL查询,减少与中的内部联接,sql,postgresql,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 el

我遇到了一些遗留代码,其中他们使用了两个内部联接,我用下面的代码替换了它们

 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

我的问题是,这是减少内部联接以提高性能的好主意吗?如果没有,我能做些什么来优化这一点,或者这是一个很好的结果?

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
表达式将null排序在非null之后,因此我们也可以使用

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

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

,并且是不同公司生产的不同软件包。即使它们都实现了SQL,它们也以不同的方式扩展SQL,有时它们使用不同的语法约定,使得它们之间的查询不兼容。请仅使用与您正在使用的软件匹配的标记。此特定更改可能对性能没有影响。最好的办法是在前后查看执行计划。更改后,它当然更具可读性。您说希望改进查询,但您希望改进哪些方面?演出可维护性?可读性?实际输出?如果您的目标是性能,请检查执行计划。您可以使用
解释(分析,缓冲区)选择..
来显示执行计划。有关更多详细信息,请参阅:有时在查询中重写大型
以使用数组会产生不同,例如
其中p.id=any(数组[1,2,…])
。请注意,
join(选择1作为id union all select 2…)as…
可以简化为
join(值(1),(2),…)as…
),因此这可能没有什么改进,只是增加了可读性。是的,这是正确的。但可读性很有价值。它使您的查询更易于维护。它不应该是
合并(NULLIF(r.sector\u id,1),2)
?(这当然很难看)@joop:No.
r.sector\u id
总是等于它自己,除非它为空。因此
case r.sector\u id当r.sector\u id然后1 else 2 end时
仅用2替换空值。并且您的版本本身替换非空值(可以是1)