【问题标题】:In SQL, how do you get the column name for largest item in a row?在 SQL 中,如何获取行中最大项目的列名?
【发布时间】:2021-10-29 22:55:18
【问题描述】:

我有一个具有唯一 ID、col1、col2、col3...等的表。除 id 列外,所有列都是数字。我需要为每个 id 提取具有最高值的列。所以假设我们有一个 id 1,col1 值为 10,col2 值为 20,col3 值为 30。结果应该是两列。 1和col3。基本上是 id 和具有最高值的列的名称。我希望这很清楚。

【问题讨论】:

  • 为什么你有 30 列?为什么不添加一个包含 1、..、30 的 col 表示 col 索引?
  • 请提供足够的代码,以便其他人更好地理解或重现问题。

标签: sql google-bigquery


【解决方案1】:

您可能应该重组您的数据。有第三个重复列是存储数据的糟糕方式。传统上,在 SQL 中,您将使用一个单独的表,每个值一行。但 BigQuery 也支持数组和 JSON 格式。

蛮力方法使用巨型case表达式:

select t.*,
       (case greatest(col1, col2, col3, . . . )
             when col1 then 'col1'
             when col2 then 'col3'
             . . .
             when col30 then 'col30'
        end) as greatest_value
from t;

【讨论】:

    【解决方案2】:

    我不确定为什么您的数据结构是这样的,但一种解决方法可能是这样的:

    • 使用GREATEST(),从传入的值中获取最大值
    SELECT
    id,
    GREATEST(col1,col2,.....col30) AS largest_value
    
    FROM [table name]
    

    【讨论】:

      【解决方案3】:

      我会去联合所有将所有列作为同一列,然后获得最大值或降序并获得前 1。

      类似这样的:

      Select id, (select top 1 name from (
      (select id, col1 col, colname name from tablename)
      union all
      (select id, col2 col, colname name from tablename)
      union all
      (select id, col3 col, colname name from tablename)
      ) as t
      where t.id = tablename.id 
      order by col desc)
      from tablename
      

      【讨论】:

        【解决方案4】:

        考虑以下使用 UNPIVOT 的方法(假设每一行都有唯一的 id)

        select as value array_agg(t order by value desc limit 1)[offset(0)]
        from (
          select * from `project.dataset.table`
          unpivot (value for col in (col1, col2, col3, col4))
        ) t
        group by id     
        

        您可以使用以下虚拟数据对其进行测试

        with `project.dataset.table` as (
          select 1 id, 11 col1, 12 col2, 13 col3, 14 col4 union all 
          select 2, 24, 23, 22, 21 union all 
          select 3, 31, 34, 32, 33
        )
        select as value array_agg(t order by value desc limit 1)[offset(0)]
        from (
          select * from `project.dataset.table`
          unpivot (value for col in (col1, col2, col3, col4))
        ) t
        group by id    
        

        有输出

        【讨论】:

          【解决方案5】:

          另一个选项 - 不需要知道列名,因此无论有多少列及其名称,都可以使用相同的查询

          select id, 
            ( select as struct split(kv, ':')[offset(0)] col, 
                cast(split(kv, ':')[offset(1)] as numeric) value
              from t.kvs as kv
              order by value desc 
              limit 1
            ).*
          from(
            select *, 
              split(translate(to_json_string((select as struct * except(id) from unnest([t]))), '{}"', '')) kvs
            from `project.dataset.table` t
          ) t         
          

          您可以使用虚拟数据进行测试,如下例所示

          with `project.dataset.table` as (
            select 1 id, 11 col1, 12 col2, 13 col3, 14 col4 union all 
            select 2, 24, 23, 22, 21 union all 
            select 3, 31, 34, 32, 33
          )
          select id, 
            ( select as struct split(kv, ':')[offset(0)] col, 
                cast(split(kv, ':')[offset(1)] as numeric) value
              from t.kvs as kv
              order by value desc 
              limit 1
            ).*
          from(
            select *, 
              split(translate(to_json_string((select as struct * except(id) from unnest([t]))), '{}"', '')) kvs
            from `project.dataset.table` t
          ) t       
          

          有输出

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2017-10-11
            • 2016-06-05
            • 2011-01-07
            • 1970-01-01
            • 2022-01-07
            • 1970-01-01
            相关资源
            最近更新 更多