【问题标题】:Count users that have purchased different products within 30 days统计 30 天内购买过不同产品的用户
【发布时间】:2016-09-19 19:12:38
【问题描述】:
 user_id    product_type  reservation_date   used_date
|12345     |     A       |   2016-06-01    | 2016-06-24 |
|12345     |     B       |   2016-06-03    | 2016-06-24 |
|12345     |     C       |   2016-07-02    | 2016-07-30 |
|12346     |     A       |   2016-06-27    | 2016-07-24 |
|12346     |     B       |   2016-06-29    | 2016-07-22 |

我想弄清楚我们平台上的“交叉销售”效应。 上表中,user_id12345在一个月(一天)内购买了product_typeABC

我想统计在reservation_date 中购买任何类型产品的用户数量,但在 30 天的时间间隔内至少购买了 2 个不同类型的产品。

有没有办法做到这一点?我已经写了一个如下所示的查询,但我认为这是不准确的,因为我无法以我希望查看输出的适当条件计算日期。

SELECT
DATE_TRUNC('month', reservation.date),
COUNT(DISTINCT(user.id)),
FROM reservation
INNER JOIN products ON products.id = reservation.product_id
INNER JOIN users ON users.id = reservation.user_id
WHERE products.type = 'A'
AND user.id IN(
SELECT user.id
FROM reservation
INNER JOIN products ON products.id = reservation.product_id
INNER JOIN users ON users.id = reservation.user_id
WHERE product.type in ('B','C')
GROUP BY 1,2 ORDER BY 1 DESC;

【问题讨论】:

  • 请更详细地定义:with the interval of 30 days in reserved date 这是绝对时间范围还是两个不同product_type 之间的最大间隔?并始终声明您的 Postgres 版本。而user.id 不是有效的列名。

标签: sql postgresql


【解决方案1】:

也许这样的事情会起作用

SELECT COUNT(DISTINCT(r.user_id))
  FROM reservation r
 INNER JOIN reservation r_a
         ON r_a.user_id = r.user_id
        AND r_a.product_type <> r.product_type
        AND @extract(day FROM (r_a.reservation_date::TIMESTAMP - r.reservation_date::TIMESTAMP)) <= 30

@extract(timepart from (one_timestamp - another_timestamp) 将等于两个时间戳之间的“timeparts”的绝对值

【讨论】:

  • 嗨!谢谢你的评论。我试过了,但在我们的预订表中,没有“产品类型”列。我必须将产品类型单独加入预订表,还有其他方法吗?真的很有帮助!谢谢。
  • 哦.. 现在我明白了。因此,如果您的数据在 product_type 和 product_id 之间具有严格的一对一关系,您可以在上面的查询中检查不匹配的 product_id 而不是 product_type。其他查询将类似于 ... FROM reservation r INNER JOIN products p ON p.id = r.product_id INNER JOIN reservation r_a ON r_a.user_id = r.user_id AND @extract(..same params..) &lt;=30 INNER JOIN products p_a ON p_a.id = r_a.product_id AND p_a.type &lt;&gt; p.type
  • 哦,是的,这只是无缝计算了所有内容 :) 非常感谢,这是完美的 :)
【解决方案2】:

基本查询可能如下所示(假设您想将每个月视为时间范围):

SELECT user_id, date_trunc('month', reservation_date)
     , count(DISTINCT product_type) AS ct
FROM   reservation
GROUP  BY 1,2
HAVING count(DISTINCT product_type) > 1
ORDER  BY 1 DESC;

要获得合格用户的实际数量:

SELECT count(DISTINCT user_id) 
FROM  (
   SELECT user_id
   FROM   reservation
   GROUP  BY user_id, date_trunc('month', reservation_date)
   HAVING count(DISTINCT product_type) > 1
   ) sub;

根据your comment

...计算每月进行预订的用户数(至少 2 产品类型),每次预订后 30 天之间有一个间隙。所以如果我 我在7月1日预订了产品A,15日预订了产品B,我 不计入该月度数字。

SELECT date_trunc('month', reservation_date), count (DISTINCT user_id) AS ct_users
FROM   reservation r
WHERE  EXISTS (
   SELECT 1
   FROM   reservation
   WHERE  user_id = r.user_id
   AND    reservation_date <= r. reservation_date - 30  -- assuming data type date!
   AND    product_type <> r.product_type
   )
GROUP  BY 1;

这会返回每个月的用户数量,而不是本月进行预订的用户数量,以及至少提前 30 天预订不同类型产品的用户数量。

在较长的一段时间内,记住之前合格的用户并只测试其余的用户会更有效率。

【讨论】:

  • 感谢您输入欧文。我想计算在每次预订后 30 天内进行预订(至少 2 种产品)的每月用户数量。因此,如果我在 7 月 1 日预订了产品 A,15 日预订了产品 B,则我不计入该月度数字。我会试试这个! :)
  • @silverrain:确切的定义应该真的是在问题中
猜你喜欢
  • 1970-01-01
  • 2023-03-13
  • 2023-01-16
  • 2018-03-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-03-13
相关资源
最近更新 更多