【问题标题】:BigQuery SQL - Create New Column Based on the Max Value from Multiple ColumnsBigQuery SQL - 根据多列的最大值创建新列
【发布时间】:2021-10-30 06:57:19
【问题描述】:

我有一张表格,其中包含有关客户的信息以及他们购买每种食物的金额。我想创建新的列,这是他们购买的最常见的食物类型。有没有有效的方法来做到这一点?

我尝试使用 case when 并进行一对一的比较,但它变得非常乏味。

样本数据:

Cust_ID apple_type1 apple_type2 apple_type3 apple_type4 apple_type5 apple_type6
1 2 0 0 3 6 1
2 0 0 0 1 0 1
3 4 2 1 1 0 1
4 5 5 5 0 0 0
5 0 0 0 0 0 0

--想要

Cust_ID freq_apple_type_buy
1 type5
2 type4 and type6
3 type1
4 type1 and type2 and type3
5 unknown

【问题讨论】:

  • 天啊,非常感谢!你编辑了什么使这个看起来正确?
  • 您是否能够/愿意更改您的源数据模型?如果您对这些数据进行了标准化(三列;cust_id、apple_type、数量),那么这将是微不足道的。
  • 使表格正确呈现的编辑是在每个表格之前有一个空行。
  • 所以,如果我的原始数据中有 3 列(三列;cust_id、apple_type、数量),要获得最频繁的苹果类型购买,我可以这样做:选择 cust_id、apply_type、max (数量)来自 xxx 组的 cust_id、apply_type?如果有多个类型的购买金额相同,我想对其进行分类怎么办?

标签: sql google-bigquery


【解决方案1】:

考虑以下方法

select Cust_ID, if(count(1) = any_value(all_count), 'unknown', string_agg(type, ' and ')) freq_apple_type_buy
from (
  select *, count(1) over(partition by Cust_ID) all_count
  from (
    select Cust_ID, replace(arr[offset(0)], 'apple_', '') type,cast(arr[offset(1)] as int64) value
    from data t,
    unnest(split(translate(to_json_string((select as struct * except(Cust_ID) from unnest([t]))), '{}"', ''))) kv,
    unnest([struct(split(kv, ':') as arr)])
  )
  where true qualify 1 = rank() over(partition by Cust_ID order by value desc)
)
group by Cust_ID    

如果应用于您问题中的样本数据 - 输出是

【讨论】:

    【解决方案2】:

    这使用 UNPIVOT 将您的列转换为行。然后使用 RANK() 为每一行分配一个排名,这意味着如果多行在数量上匹配,它们共享相同的排名。

    然后它只选择 rank=1 的产品(可能是多行,如果多个产品并列第一)

    WITH
      normalised_and_ranked AS
    (
      SELECT
        cust_id,
        product,
        qty,
        RANK() OVER (PARTITION BY cust_id ORDER BY qty DESC) AS product_rank,
        ROW_NUMBER() OVER (PARTITION BY cust_id ORDER BY qty DESC) AS product_row
      FROM
         yourData
      UNPIVOT(
        qty FOR product IN (apple_type1, apple_type2, apple_type3, apple_type4, apple_type5, apple_type6)
      )
    )
    SELECT
      cust_id,
      CASE WHEN qty = 0 THEN NULL ELSE product END   AS product,
      CASE WHEN qty = 0 THEN NULL ELSE qty END   AS qty
    FROM
      normalised_and_ranked
    WHERE
      (product_rank = 1 AND qty > 0)
      OR
      (product_row = 1)
    

    编辑:添加 fudge 以确保在所有 qty 均为 0 时返回空行。

    (通常我不会为此类客户返回一行。)

    【讨论】:

      猜你喜欢
      • 2022-10-13
      • 1970-01-01
      • 2015-04-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-04-21
      • 2014-10-05
      相关资源
      最近更新 更多