对sql中的两个独立列使用groupby来计算一个新列

a14dhokn  于 2021-07-24  发布在  Java
关注(0)|答案(3)|浏览(320)

我有一个名为transactions的mysql表,如下所示:

|---------|--------------|--------------|--------------------------|
|order_id |customer_name |  brand_name  |   order_time_stamp       | 
|---------|--------------|--------------|--------------------------|
|   1     | Jack         |  Pepsi       | 2019-02-23 20:02:21.550. |
|---------|--------------|--------------|--------------------------|
|   2     | Dorothy      |  Fanta       | 2019-02-23 20:03:21.550. |
|---------|--------------|--------------|--------------------------|
|   3     | Dorothy      |  Fanta       | 2019-02-23 20:04:21.550. |
|---------|--------------|--------------|--------------------------|
|   4     | Jack         |  Fanta       | 2019-02-23 20:05:21.550. |
|---------|--------------|--------------|--------------------------|

很明显,这是一个表,它捕获在线商店中的每个订单,订单id是主键。我试图捕捉的是按品牌名称分组的额外订单数量,如下所示:

enter code here
|------------|--------------------|
| brand_name | additional orders  |
|------------|--------------------| 
| Pepsi      |         0          |
|------------|--------------------| 
| Fanta      |         1          | 
|------------|--------------------|

但是,附加订单是在客户级别上定义的,并且是客户第一个订单之后所有订单的总和。
我的策略是使用rank()函数,如下所示:

select rank() over( partition by customer_name order by order_time_stamp) as rank
from transactions

这将创建一个附加列,该列将为每个客户创建一个排名。然而,我不知道现在如何在一个品牌级别上进行分组,并得到我已经展示的输出

8gsdolmq

8gsdolmq1#

你可以用 row_number() 若要对每个客户的订单进行排序,请筛选“附加”订单(即排名大于1的每个订单),然后按 brand_name :

select brand_name, count(*) no_additional_orders
from (
    select 
        t.*, 
        row_number() over(partition by customer_name order by order_time_stamp) rn
    from transactions t
) t
where rn > 1
group by brand_name

如果您还想考虑没有额外订单的品牌,则可以将过滤逻辑移到聚合函数:

select brand_name, sum(rn > 1) no_additional_orders
from (
    select t.*, row_number() over(partition by customer_name order by order_time_stamp) rn
    from transactions t
) t
group by brand_name
nhaq1z21

nhaq1z212#

你的数据相当混乱。我想你想要的是最早的时间戳,而不是最早的订单。这是一个微妙的区别,但很重要:

select brand_name,
       sum(order_time_stamp > min_ots)
from (select t.*, min(order_time_stamp) over (partition by customer_name) as min_ots
      from t
     ) t
group by brand_name;

你可以做类似的事情 rank() 也:

select brand_name,
       sum(seqnum > 1)
from (select t.*, 
             rank() over (partition by customer_name order by order_time_stamp) as seqnum
      from t
     ) t
group by brand_name;
eanckbw9

eanckbw93#

你想把每个人的所有顺序加起来 customer_namebrand_name 除了1,因为你不想在每个客户的第一个订单的总和。
您可以通过从订单总数中减去订购产品的不同客户的数量来完成,该数量等于每个客户的第一个订单数量:

select brand_name, 
       count(*) - count(distinct customer_name) additional_orders
from transactions
group by brand_name

请看演示。
结果:

> brand_name | additional_orders
> :--------- | ----------------:
> Pepsi      |                 0
> Fanta      |                 1

相关问题