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

And*_*rew 1 postgresql join

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

\n\n

表格

\n\n

我的PRICE_LIST桌子:

\n\n
price_list_id\nprice_number\nname\n
Run Code Online (Sandbox Code Playgroud)\n\n

该表有 41 行。

\n\n

我的SKU_PRICE桌子:

\n\n
sku_id\nprice_number\n
Run Code Online (Sandbox Code Playgroud)\n\n

该表有 1,132 行。

\n\n

我的CUSTOMER桌子:

\n\n
customer_id\nprice_number\ncustomer_type\nis_active\n
Run Code Online (Sandbox Code Playgroud)\n\n

该表有 6,535 行,但我只想要活跃的“E”类型客户,因此我想要的行数下降到 2,961。

\n\n

询问

\n\n

我的查询:

\n\n
SELECT\n  pl.price_list_id,\n  pl.price_number,\n  pl.name,\n  count(sp.sku_id)     "sku_count",\n  count(c.customer_id) "customer_count"\nFROM price_list pl\n  LEFT JOIN sku_price sp ON (sp.price_number = pl.price_number)\n  LEFT JOIN customer c ON (c.price_number = pl.price_number)\nWHERE c.customer_type = \'E\' AND c.is_active = \'T\'\nGROUP BY pl.price_list_id, pl.price_number, pl.name;\n
Run Code Online (Sandbox Code Playgroud)\n\n

问题

\n\n

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

\n\n
 price_list_id | price_number | name  | sku_count | customer_count\n---------------+--------------+-------+-----------+----------------\n            31 |            4 | SF0   |         0 |            792\n            33 |            6 | SF2   |     30525 |          30525\n             2 |            2 | ASNP2 |       972 |            972\n             1 |            1 | ASNP1 |      1596 |           1596\n            34 |            7 | SF3   |       616 |            616\n            37 |           10 | SF6   |         0 |             51\n            32 |            5 | SF1   |      1144 |           1144\n
Run Code Online (Sandbox Code Playgroud)\n\n

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

\n\n

如果我PRICE_LIST只加入一个表 \xe2\x80\x94 或SKU_PRICE\ CUSTOMERxe2\x80\x94 我会得到合理的结果。只有当我尝试同时做这两件事时,它才会出现问题。

\n\n

如果有人能将我推向正确的方向,我将非常感激。

\n\n

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

\n

Rom*_*kar 6

如果我理解你的模式,你可以做类似的事情

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;
Run Code Online (Sandbox Code Playgroud)

但就性能而言,我认为这样做会更好:

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
Run Code Online (Sandbox Code Playgroud)