在PostgreSQL中连接多个表,并计算连接的表行

时间:2015-01-08 12:17:48

标签: postgresql join

我有三张桌子。我试图查询我的PRICE_LIST表,并计算每个价目表中有价格的SKU数量,以及分配给每个价目表的客户数量。

我的PRICE_LIST表:

price_list_id
price_number
name

此表有41行。

我的SKU_PRICE表:

sku_id
price_number

此表有1,132行。

我的CUSTOMER表:

customer_id
price_number
customer_type
is_active

此表有6,535行,但我只想要类型为#34; E"这是有效的,所以我想要的行数下降到2,961。

查询

我的查询:

SELECT
  pl.price_list_id,
  pl.price_number,
  pl.name,
  count(sp.sku_id)     "sku_count",
  count(c.customer_id) "customer_count"
FROM price_list pl
  LEFT JOIN sku_price sp ON (sp.price_number = pl.price_number)
  LEFT JOIN customer c ON (c.price_number = pl.price_number)
WHERE c.customer_type = 'E' AND c.is_active = 'T'
GROUP BY pl.price_list_id, pl.price_number, pl.name;

问题

我遇到的问题是结果很疯狂:

 price_list_id | price_number | name  | sku_count | customer_count
---------------+--------------+-------+-----------+----------------
            31 |            4 | SF0   |         0 |            792
            33 |            6 | SF2   |     30525 |          30525
             2 |            2 | ASNP2 |       972 |            972
             1 |            1 | ASNP1 |      1596 |           1596
            34 |            7 | SF3   |       616 |            616
            37 |           10 | SF6   |         0 |             51
            32 |            5 | SF1   |      1144 |           1144

我获得了SKU数量和客户数量的计数30,525这一事实告诉我,联接正在做奇怪的事情。我也不明白为什么我没有得到没有产品和没有客户的价格表(而且还有很多客户)。

如果我将PRICE_LIST加入一个表格 - SKU_PRICECUSTOMER - 我会得到明智的结果。只有当我尝试同时做两件事时才会这样做。

如果有人能够朝着正确的方向推动我,我真的很感激。

FWIW,我在OS X上使用PostgreSQL 9.3.5。

1 个答案:

答案 0 :(得分:4)

如果我了解您的架构,您可以执行类似

的操作
select
    pl.price_list_id,
    pl.price_number,
    pl.name,
    count(distinct sp.sku_id) as "sku_count",
    count(distinct c.customer_id) as "customer_count"
from price_list pl
    left outer join sku_price as sp on sp.price_number = pl.price_number
    left outer join customer as c on c.price_number = pl.price_number
where c.customer_type = 'E' and c.is_active = 'T'
group by pl.price_list_id, pl.price_number, pl.name;

但是表现明智我认为这样做会更好:

with cte_sku_price as (
     select count(*) as cnt, price_number from sku_price group by price_number
), cte_customer as (
     select count(*) as cnt, price_number
     from customer
     where customer_type = 'E' and is_active = 'T'
     group by price_number
)
select
    pl.price_list_id,
    pl.price_number,
    pl.name,
    sp.cnt as "sku_count",
    c.cnt as "customer_count"
from price_list pl
    left outer join cte_customer as c on c.price_number = pl.price_number
    left outer join cte_sku_price as sp on sp.price_number = pl.price_number