【问题标题】:Joining multiple tables in PostgreSQL, and counting joined table rows在 PostgreSQL 中连接多个表,并计算连接表的行数
【发布时间】:2015-01-08 12:17:47
【问题描述】:

我有三张桌子。我正在尝试查询我的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 行,但我只想要“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。

【问题讨论】:

    标签: postgresql join


    【解决方案1】:

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

    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
    

    【讨论】:

    • 那种只是掩盖了问题,我想。它仍然没有正确加入。例如,我有一个价格编号 41,它有 896 种产品且没有客户,但输出中没有提供它。
    • @Andrew 查看我的下一个查询,如果您想查看那些没有客户的人,您必须将 inner join 更改为 left outer join
    • 宾果游戏。这很好用。有空白而不是 0 表示没有加入,但我可以忍受。
    • @Andrew,您可以使用“COALESCE”函数将任何空值转换为零,即 COALESCE(c.cnt,0)...
    猜你喜欢
    • 1970-01-01
    • 2021-07-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-22
    • 1970-01-01
    相关资源
    最近更新 更多