【问题标题】:Use Group By against two separate columns in SQL to compute a new column对 SQL 中的两个单独列使用 Group By 来计算新列
【发布时间】:2020-07-19 21:16:28
【问题描述】:

我有一个名为 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. |
|---------|--------------|--------------|--------------------------| 

很明显,这是一个以 order_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

这会创建一个额外的列,为每个客户创建一个排名。但是,我不确定现在如何将其分组到品牌级别并获得我所展示的输出

【问题讨论】:

  • 为什么不是《芬达》2呢?杰克和多萝西都有芬达的第二笔订单。
  • 额外的订单数量是品牌级别的..当杰克订购芬达时,这是第一次发生。
  • 你们需要组队。

标签: mysql sql


【解决方案1】:

您可以使用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

【讨论】:

    【解决方案2】:

    您的数据相当混乱。我认为您想要最早的时间戳之后的所有内容,而不是最早的顺序。这是一个微妙的区别,但很重要:

    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;
    

    【讨论】:

      【解决方案3】:

      您希望将每个customer_name 的所有订单与brand_name 的所有订单相加,但 1 除外,因为您不希望每个客户的第一个订单相加。
      您可以通过从订单总数中减去订购产品的不同客户的数量来做到这一点,该数量等于每个客户的第一个订单数量:

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

      请参阅demo
      结果:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-10-07
        • 1970-01-01
        • 1970-01-01
        • 2012-09-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多