简体   繁体   English

如何计算每个客户的首次购买和退货购买?

[英]How to calculate first purchase and returning purchase for each customer?

I have a table of transaction, like this:我有一张交易表,如下所示:

CREATE TABLE IF NOT EXISTS `transactions` (
  `id` varchar(250) NOT NULL PRIMARY KEY,
  `date` DATE NOT NULL,
  `value` int NOT NULL,
  `customer` varchar(250) NOT NULL
);

INSERT INTO `transactions` VALUES
  ('001', '2020-12-17', 45000, 'JOHN'),
  ('002', '2020-12-25', 5000, 'MARY'),
  ('003', '2021-04-17', 1500, 'MARY'),
  ('004', '2020-06-01', 400, 'JOHN'),
  ('005', '2020-06-06', 6000, 'JOHN');

I want to calculate first purchase value and returning purchase value from each customer .我想计算每个customerfirst purchase valuereturning purchase value I can make the select statement for first purchase value, but kind of confuse to make the returning purchase value.我可以为首次购买价值制作 select 声明,但在制作退货购买价值时有点混淆。 My query for first purchase value is like this:我对首次购买价值的查询是这样的:

SELECT customer, value as first_purchase_value, MIN(date) as first_purchase_value_date FROM orders  
GROUP BY customer

I also have one problem which I don't want to inclide minimum date into the select statement but then I can't get the first purchase value.我也有一个问题,我不想在 select 语句中包含最小日期,但是我无法获得第一次购买价值。 The expected output is like this:预期的 output 是这样的:

customer顾客 first_purchase_value first_purchase_value returning_purchase_value退货购买价值
JOHN约翰 45000 45000 6000 6000
MARY玛丽 5000 5000 1500 1500

I think, its can be done with LIMIT and SORT BY , but I don't know.我认为,它可以用LIMITSORT BY来完成,但我不知道。 Any idea how to solve this problem?知道如何解决这个问题吗?

EDIT编辑

Here's the fiddle: http://sqlfiddle.com/#!9/34daa6/3这是小提琴: http://sqlfiddle.com/#!9/34daa6/3

Thanks for the Fiddle.感谢小提琴。 Somehow I have a hard time using it.不知何故,我很难使用它。 So I copied your code and put in my MS SQL Server.所以我复制了你的代码并放入了我的 MS SQL 服务器。 The syntax will be a bit different but it should get the job done.语法会有些不同,但它应该可以完成工作。

Here is how I did it:这是我的做法:

with cte_date_info as
 (
     select customer, min(date) as min_date, max(date) as max_date
     from transactions
     group by customer
 
 ),
 
 cte_first_purchase as
 (
     select customer, value as first_purchase
     from transactions
     where date IN
        (
        select min_date as date 
        from cte_date_info
        )   
 ),
 
 cte_second_purchase as
 (
     select customer, value as second_purchase
     from transactions
     where date IN
        (
        select max_date as date 
        from cte_date_info
        )   
 
 )
 
 select t1.*, t2.second_purchase
 from cte_first_purchase as t1
 left join cte_second_purchase as t2
 on t1.customer = t2.customer

I think if this is a homework, you would want to check if a customer can have more than 1 transaction in 1 day.我认为如果这是一项家庭作业,您会想检查客户是否可以在 1 天内进行超过 1 笔交易。 If it's the case you will need some group by and sum().如果是这种情况,您将需要一些 group by 和 sum()。 But if only 1 transaction per day, the CTE should do the trick.但如果每天只有 1 笔交易,CTE 应该可以解决问题。

======== ========

I think you example is inconsistent.我认为你的例子是不一致的。 For Mary, the subsequent purchase is 1500 which is the next purchase.对于 Mary,下一次购买是 1500,即下一次购买。 But for John, his next purchase should be 400. But you put in 6000 which is the 3rd purchase.但是对于 John,他的下一次购买应该是 400。但是您输入了 6000,这是第三次购买。

So, do you want it to be 400, 6000, or 6400 (400 + 6000)?那么,您希望它是 400、6000 还是 6400(400 + 6000)?

====== ======

I cannot help with the actual code as I don't have such data in my database.我无法提供实际代码,因为我的数据库中没有此类数据。

But conceptually, this is what I would do,但从概念上讲,这就是我要做的,

With cte_first_purchase as
(
Calculate the first purchase of each customer
You can use rank to only keep the minimum purchase date of each person. But be depending on data structure though as each person can purchase more than once in a day.
),

With cte_subsequent_purchse as
(
calculate the subsequent purchase of each customer.

You can still use rank here but this time instead of using where = 1, then you go with where = 2. Then you will keep all the subsequent purchase, then sum the purchases if a customer buys more than once in the same day.
)

Select t1.*, t2.*
from cte_first_purchase as t1
left join cte_subsequent_purchase as t2
on t1.name = t2.name

If you can provide a code to create sample tables, I can help with more concrete codes.如果您可以提供创建示例表的代码,我可以提供更具体的代码。

As your comment, you can rename lastest_purchase_value as returning_... but I thing latest is more understandable作为您的评论,您可以将 lastest_purchase_value 重命名为returning_...但我认为最新的东西更容易理解

    SELECT customer,first_purchase_value,latest_purchase_value FROM 
 ( SELECT customer, value as first_purchase_value,MIN(date) FROM transactions GROUP BY customer ) r1
 JOIN 
 ( SELECT customer, value as latest_purchase_value,MAX(date) FROM transactions  GROUP BY customer) r2
 USING (customer);

you can try this query:你可以试试这个查询:

SELECT  customer
    , SUBSTRING_INDEX(GROUP_CONCAT(value order by `id`),',',1) AS first_purchase_value
    , SUBSTRING_INDEX(GROUP_CONCAT(value order by `id`),',',-1) AS returning_purchase_value
    FROM transactions
    GROUP by customer;

sample样本

    MariaDB [bernd]> select * from transactions;
    +-----+------------+-------+----------+
    | id  | date       | value | customer |
    +-----+------------+-------+----------+
    | 001 | 2020-12-17 | 45000 | JOHN     |
    | 002 | 2020-12-25 |  5000 | MARY     |
    | 003 | 2021-04-17 |  1500 | MARY     |
    | 004 | 2020-06-01 |   400 | JOHN     |
    | 005 | 2020-06-06 |  6000 | JOHN     |
    +-----+------------+-------+----------+
    5 rows in set (0.00 sec)
    
    MariaDB [bernd]> SELECT customer
    -> , SUBSTRING_INDEX(GROUP_CONCAT(value order by `id`),',',1) AS first_purchase_value
    -> , SUBSTRING_INDEX(GROUP_CONCAT(value order by `id`),',',-1) AS returning_purchase_value
    -> FROM transactions
    -> GROUP by customer;
+----------+----------------------+--------------------------+
| customer | first_purchase_value | returning_purchase_value |
+----------+----------------------+--------------------------+
| JOHN     | 45000                | 6000                     |
| MARY     | 5000                 | 1500                     |
+----------+----------------------+--------------------------+
2 rows in set (0.09 sec)

MariaDB [bernd]> 

NOTE: you must also add 1 index over customer plus date to have a better performance注意:您还必须在客户加日期上添加 1 个索引以获得更好的性能

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM