【问题标题】:Faster CROSS JOIN alternative - PostgreSQL更快的 CROSS JOIN 替代方案 - PostgreSQL
【发布时间】:2011-01-05 05:50:13
【问题描述】:

我正在尝试交叉连接两个表,即客户和项目,这样我就可以按客户逐项创建销售报告。我有 2000 个客户和 2000 个项目。

SELECT customer_name FROM customers; --Takes 100ms

SELECT item_number FROM items; --Takes 50ms

SELECT customer_name, item_number FROM customers CROSS JOIN items; Takes 200000ms

我知道这是 400 万行,但是否有可能让它运行得更快?我想最终加入这样的销售表:

SELECT customer_name, item_number, sales_total FROM customers CROSS JOIN items LEFT JOIN sales ON (customer.customer_name = sales.customer_name, item.item_number=sales.item_number);

sales 表显然不会包含所有客户或所有商品,因此这里的目标是生成一份报告,显示所有客户和所有商品以及已售出和未售出的商品。

我使用的是 PostgreSQL 8.4

【问题讨论】:

  • 您是否实际上希望显示所有客户/项目的所有组合,即使他们没有,我的意思是给定的客户可能只有 1 个项目,然后您可能会显示 1999 年不需要的项目?
  • 实际上,我这样做是因为我想看看那个客户没有订购什么,所以我可以尝试卖给他们。
  • 我实际上有同样的问题,而不是客户和项目,我有资产,其价格以美元和美元在单独的表 2000 x 80 中转换为其他货币,我正在尝试交叉除了我还想将这个交叉连接的结果与另一个表进行内部连接之外,有没有办法指定交叉连接中的计算列应该是主键还是唯一的?

标签: postgresql cross-join


【解决方案1】:

回答您的问题:不,您不能比这更快地进行交叉连接 - 如果可以,那么这就是 CROSS JOIN 的实施方式。

但你真的不想要交叉连接。您可能需要两个单独的查询,一个列出所有客户,另一个列出所有商品以及它们是否已售出。

【讨论】:

  • 我必须在应用程序级别尝试两个查询,看看循环遍历所有客户和项目组合是否更快。但是,如果应用程序可以比数据库更快地完成它,我会感到惊讶。
【解决方案2】:

这确实需要多个报告。我能想到几个可以更有效地打包信息的方法:

  1. 报告:按客户/商品统计的所有购买次数(显而易见)。
  2. 报告:客户未购买的所有商品的列表。
  3. 报告:报告 #2(项目计数)的摘要,以便优先关注哪些客户。
  4. 报告:所有未购买商品的客户的列表。
  5. 报告:报告 #3(客户计数)的摘要,以确定最受欢迎和最不受欢迎的项目,以便进一步采取行动。
  6. 报告:过去购买过某件商品但在其报告期内未购买过的所有客户的列表。此报告仅在销售表有日期并且预期客户是常客(即一次性小部件)时才相关。不适用于服务合同之类的事情。

这里的重点是,不应坚持该工具一次处理所有可能的结果并生成更多数据,任何人都可以手动消化。人们应该让数据的最终用户和消费者了解他们的需求,并调整输出以满足这些需求。从长远来看,这将使双方的生活更加轻松。

【讨论】:

    【解决方案3】:

    我无法想象会有第三方解决方案来解决这个问题,PostgreSQL 程序员最了解他们的系统并将对其进行大量优化。

    【讨论】:

      【解决方案4】:

      如果您希望查看给定客户的所有物品(即使 cient 没有物品),我宁愿尝试

      SELECT c.customer_name, i.item_number, s.sales_total
      FROM customers c LEFT JOIN 
          sales s ON c.customer_name = s.customer_name LEFT OIN
          items i on i.item_number=s.item_number
      

      这应该为您提供所有客户的列表,以及销售加入的所有项目。

      【讨论】:

      • 这只会为您提供每个客户订购的商品,而不是为每个客户订购或不订购的所有商品。所以我不能说每个客户没有购买什么。
      【解决方案5】:

      也许你想要这样的东西?

      select c.customer_name, i.item_number, count( s.customer_name ) as total_sales
      from customers c full join sales s on s.customer_name = c.customer_name
      full join items i on i.item_number = s.item_number
      group by c.customer_name, i.item_number
      

      【讨论】:

        猜你喜欢
        • 2018-12-11
        • 2012-07-05
        • 2012-01-23
        • 2013-07-13
        • 2011-02-27
        • 2010-09-22
        • 2017-05-15
        • 1970-01-01
        相关资源
        最近更新 更多