SQL 按最初购买的产品列出其他购买的产品并计算买家

Posted

技术标签:

【中文标题】SQL 按最初购买的产品列出其他购买的产品并计算买家【英文标题】:SQL List other products bought and count buyers, by product originally purchased 【发布时间】:2018-09-01 23:30:09 【问题描述】:

经过多年阅读答案,终于到了我自己提出问题的时候了。

我有一份购买的产品列表和唯一的客户 ID:

+---------+--------+
| Product | Buyer  |
+---------+--------+
| Apples  | Rod    |
| Apples  | Jane   |
| Apples  | Freddy |
| Bananas | Rod    |
| Bananas | Jane   |
| Bananas | Freddy |
| Bananas | Zippy  |
| Pears   | Rod    |
| Pears   | Zippy  |
+---------+--------+

我想在 Netezza SQL 中生成以下输出:

+-----------+-------------+------------------------+---------------------+
| Product A | Buyers of A | A Buyers Also Bought B | No of A Buyers of B |
+-----------+-------------+------------------------+---------------------+
| Apples    |           3 | Bananas                |                   3 |
| Apples    |           3 | Pears                  |                   1 |
| Bananas   |           4 | Apples                 |                   3 |
| Bananas   |           4 | Pears                  |                   2 |
| Pears     |           2 | Apples                 |                   1 |
| Pears     |           2 | Bananas                |                   2 |
+-----------+-------------+------------------------+---------------------+

..这样我就可以看到每个产品的总购买者。至关重要的是,我还想查看对于每种产品,在这些购买者中,有多少人购买了同一列表中的其他产品。 编辑:重要的是要重申,如果他们没有购买产品 A,我不应该让任何买家出现在 B 的列中。

请问最有效的方法是什么?

(然后我会计算出 B 购买 A 的百分比,但这部分很简单)。

谢谢!

【问题讨论】:

【参考方案1】:

您可以创建计数摘要,然后与自身交叉连接,排除相同的匹配项。

像这样:

SELECT 
    A.Product,
    A.Buyers,
    B.Product,
    B.Buyers
FROM (
    SELECT
        Product
        count(*) AS Buyers
    FROM
        ProductBuyers
    GROUP BY
) AS A
CROSS JOIN (
    SELECT
        Product
        count(*) AS Buyers
    FROM
        ProductBuyers
    GROUP BY
) AS B
WHERE 
    A.Product != B.Product

【讨论】:

感谢您的快速响应!但是,这似乎对我不起作用 - 每个产品的两列中的数字都是相同的(每次只给我表格中的总数)。他们只是订购不同。为了让它运行,我还必须在子查询 A 和 B 中的每个 GROUP BY 和 Product 后面添加“1”。【参考方案2】:

普通购买的基本数据是自加入和group by

select p1.product, p2.product, count(*) as in_common
from purchases p1 join
     purchases p2
     on p1.buyer = p2.buyer
group by p1.product, p2.product;

要获得一个(或另一个)的计数,则为join

select p1.product, p2.product, pp.cnt, count(*) as in_common
from purchases p1 join
     purchases p2
     on p1.buyer = p2.buyer join
     (select p1.product, count(*) as cnt
      from purchases
      group by p1.product
     ) pp
     on pp.product = p1.product
group by p1.product, p2.product, pp.cnt;

或者,您可以使用窗口函数:

select p1.product, p1.cnt, p2.product, count(*) as in_common
from (select p1.*,
             count(*) over (partition by p1.product) as cnt
      from purchases p1
     ) p1 join
     purchases p2
     on p1.buyer = p2.buyer
group by p1.product, p2.product, p1.cnt;

Here 是一个 rextester,显示它正在工作。

【讨论】:

也感谢您的快速响应!不幸的是,我得到的结果与 Alan 的代码相同。无论如何,它只是给了我每种产品的总计数。可能我在最初的问题中没有说得足够清楚 - 我只在第二个计数中寻找 both 产品的买家,而不是所有买家。输出表应该更清楚地说明这一点。当然,除非我使用的代码不正确。 @baaweepgranna 。 . .这根本不是真的,除非 Netezza 被破坏了。我已经包含了一个 Rextester,它显示它在 Postgres 中工作。

以上是关于SQL 按最初购买的产品列出其他购买的产品并计算买家的主要内容,如果未能解决你的问题,请参考以下文章

SQL查询以获取购买其他客户购买的产品的客户

如何列出客户未购买的产品?

SQL Server 如何找到从每个商店购买产品的客户?

GA BigQuery - 购买产品 x 的用户也购买了产品 abc 然后仅过滤列出完整的交易,其中 x 是交易的一部分

在 WooCommerce 订单页面上列出单独购买的产品的类别和子类别

从 PaymentIntent 获取购买的产品