加入后聚合而不重复

时间:2014-11-07 11:02:13

标签: sql postgresql select join

考虑这个问题:

select
   count(p.id),
   count(s.id),
   sum(s.price)
from 
   (select * from orders where <condition>)   as s,
   (select * from products where <condition>) as p
where 
   s.id = p.order;

例如,产品中有200条记录,订单中有100条记录(一个订单可以包含一个或多个产品)。

我需要加入然后加入:

  1. 计算产品(应返回200)
  2. 计算订单(应返回100)
  3. 按订单字段之一求和(应按100价格返还总和)
  4. 问题是在加入 p 并且 s 具有相同的长度和 2)之后我可以写 count(不同的s。 id),但是对于 3)我正在获得重复项(例如,如果销售有2个产品,它的价格总和两次)所以总和适用于整个200个记录集,但应该仅查询100。

    任何想法如何总和只有来自联合表的不同记录,但也不会破坏其他选择?

    示例,已连接表

    id sale price
    0  0    4
    0  0    4
    1  1    3
    2  2    4
    2  2    4
    2  2    4
    

    所以 sum(s.price)将返回:

    4+4+3+4+4+4=23
    

    但我需要:

    4+3+4=11
    

3 个答案:

答案 0 :(得分:1)

如果products表实际上更像是一个“订单行”表,那么查询就有意义了。你可以通过几种方式做你想做的事。在这里,我将建议条件聚合:

select count(distinct p.id), count(distinct s.id),
       sum(case when seqnum = 1 then s.price end)
from (select o.* from orders o where <condition>) s join
     (select p.*, row_number() over (partition by p.order order by p.order) as seqnum
      from products p
     where <condition>
     ) p
     on s.id = p.order;

通常,名为“products”的表每个产品会有一行,其中包含描述和名称。一个名为“OrderLines”或“OrderProducts”或“OrderDetails”的表将使给定订单中的产品。

答案 1 :(得分:0)

您对单个产品记录不感兴趣,但仅限于其编号。因此,加入聚合(每个订单一个记录)而不是单个行:

select
  count(*) as count_orders,
  sum(p.cnt) as count_products,
  sum(s.price)
from orders as s
join 
(
  select order, count(*) as cnt 
  from products 
  where <condition> 
  group by order
) as p on p.order = s.id
where <condition>;

答案 2 :(得分:0)

您的主要问题是桌面设计。如果产品没有销售,您目前无法了解产品的价格。价格应该在产品表中。一个产品需要一定的价格。然后,您可以计算销售的所有产品,并获得销售的总价格。

另外,为什么使用子查询?执行此操作时,在连接两个子查询时不会使用任何索引。如果您的联接是那么复杂的使用视图。在大多数数据库中,他们可以编入索引