繁体   English   中英

除了使用相关查询来解决以下问题之外,还有更有效的方法吗?

[英]Is there a more efficient approach other than using a co-related query for solving the below problem?

我有三个数据库表:

  • product
  • product_manufacturer
  • product_manufacturer_warranties

product 表与 product_manufacturer 具有一对一的映射关系,product_id 存储在 product_manufacturer 表中。 product_manufactuer 表与 product_manufacturer_warranties 表具有一对多映射。

我需要编写一个查询来检索 product 表中的所有列和其他两个列,这两个列可用于分别确定 product 和 product_manufacturer 以及 product_manufacturer 和 product_manufactuer_warranties 是否存在有效连接。

我编写了以下可以处理上述情况的相关查询:

select product.*, pm.web_id,
        (   SELECT count(*)
            FROM product_manufacturer_warranty pmw
            WHERE pm.web_id = pmw.product_manufacturer_id)
            AS total_warranties
from product
left join product_manufacturer pm on product.web_id = pm.product_id

我想知道在 PostgreSQL 服务器上使用 SQL 是否有更好或更有效的方法来实现此目的。

进行一次聚合,然后加入结果:

select product.*, 
       pm.web_id,
       pmw.total_warranties
from product
  left join product_manufacturer pm on product.web_id = pm.product_id
  left join (   
     SELECT product_manufacturer_id, count(*) as total_warranties
     FROM product_manufacturer_warranty pmw
     group by product_manufacturer_id
  ) as pmw on pm.web_id = pmw.product_manufacturer_id)

由于您只对bare existence感兴趣,所以不要运行可能更昂贵的 count()
在对(可能很大的)表格进行分页时,不要计算所有产品的数量,这会更加昂贵。

这应该为您提供最佳性能:

向上翻页:

SELECT p.*
     , m.product_id IS NOT NULL AS has_maufacturer
     , EXISTS (
         SELECT FROM product_manufacturer_warranty w
         WHERE  w.product_manufacturer_id = m.web_id
         ) AS has_warranties
FROM  (
   SELECT *
   FROM   product
   WHERE  product_id > $max_product_id_of_last_page
   -- more filters here?
   ORDER  BY product_id
   LIMIT  $page_size
   ) p
LEFT   JOIN product_manufacturer m ON p.web_id = m.product_id

查询返回您要求的内容:

product 表中的所有列和其他两个列,可用于确定productproduct_manufacturer以及product_manufacturerproduct_manufactuer_warranties是否存在有效连接。

  • 子查询p中第 select 个感兴趣的产品
  • 然后左连接到product_manufacturer 不能乘行,定义为一对一关系!
  • 然后使用EXISTS检查是否存在。 如果可以有很多相关行,成本会大大降低。 看:

相应地向下翻页:

SELECT p.*
     , m.product_id IS NOT NULL AS has_maufacturer
     , EXISTS (
         SELECT FROM product_manufacturer_warranty w
         WHERE  w.product_manufacturer_id = m.web_id
         ) AS has_warranties
FROM  (
   SELECT *
   FROM   product
   WHERE  product_id < $min_product_id_of_last_page
   -- more filters here?
   ORDER  BY product_id DESC
   LIMIT  $page_size
   ) p
LEFT   JOIN product_manufacturer m ON p.web_id = m.product_id
ORDER  BY product_id;

适应您的实际排序顺序。 这对于多个ORDER BY表达式来说更棘手。 无论哪种方式,除非您的桌子非常小,否则不要LIMIT / OFFSET 看:

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM