【问题标题】:How do we find frequency of one column based off two other columns in SQL?我们如何根据 SQL 中的其他两列找到一列的频率?
【发布时间】:2020-11-12 10:12:10
【问题描述】:

我对使用 SQL 比较陌生,无法找到任何过去的线程来解决我的问题。我在一个表中有三列,列是名称、客户和位置。我想添加一个附加列,根据名称和客户(前两列)确定哪个位置最常见。

我添加了一张示例照片,其中我创建的列中的 name-Jane customer-BEC 将是“Texas”,因为它出现了 2 次,而加利福尼亚则出现了 1 次。有没有办法实现这个?

【问题讨论】:

  • 是否会将“Texas”分配给带有 ARC 的行?
  • 其中一个答案是否符合您的要求?如果是这样,请投票并选择您喜欢的解决方案。谢谢!

标签: sql oracle join oracle-sqldeveloper


【解决方案1】:

如果你想在所有四行都使用'Texas'

select t.Name,  t.Customer, t.Location,
      (select t2.location 
       from table1 t2
       where t2.name = t.name
       group by name, location
       order by count(*) desc
       fetch first 1 row only
      ) as most_frequent_location
from table1 t ;

您也可以使用分析函数来做到这一点:

select t.Name,  t.Customer, t.Location,
       max(location) keep (dense_rank first order by location_count desc) over (partition by name) most_frequent_location
from (select t.*,
             count(*) over (partition by name, customer, location) as location_count
      from table1 t 
     ) t;

Here 是一个 dbfiddle。

这两个版本都将'Texas' 放在所有四行中。但是,每个都可以通过最小的努力将'California' 放在 ARC 的行中。

【讨论】:

    【解决方案2】:

    在 Oracle 中,您可以使用 aggregate function stats_mode() 计算组中出现次数最多的值。

    不幸的是,它没有作为窗口函数实现。所以一个选项使用聚合子查询,然后与原始表连接:

    select t.*, s.top_location
    from mytable t
    inner join (
        select name, customer, stats_mode(location) top_location
        from mytable
        group by name, customer
    ) s where s.name = t.name and s.customer = t.customer
    

    您也可以使用相关子查询:

    select 
        t.*,
        (
            select stats_mode(t1.location) 
            from mytable t1 
            where t1.name = t.name and t1.customer = t.customer
        ) top_location
    from mytable t
    

    【讨论】:

      【解决方案3】:

      这更多是关于理解关系数据库概念的问题。如果您想要该信息,则不会将其放在附加列中。它是在多列上计算的数据 - 为什么将其存储在表本身中?编码很复杂,而且对数据库来说也很昂贵(想象一下,如果有人插入一百万行,你必须计算所有行的值) 相反,您可以执行以下操作之一

      • 在运行时计算,如其他答案所示
      • 如果你想让它更持久,你可以在视图中嵌入上面的查询
      • 如果您想物理存储信息,可以使用物化视图

      官方 oracle 文档中有大量关于这 3 个选项的文档

      【讨论】:

      • 好点。我想说,在这种情况下,物化视图会很好地为您服务。
      【解决方案4】:

      您的第一步是构建一个查询来确定最频繁的位置,这很简单:

      select Name, Customer, Location, count(*)
      from table1 
      group by Name, Customer, Location
      

      这不是立即有用的,但可以在 row_number() 中使用该逻辑,它为返回的每一行提供一个唯一的 id。在下面的查询中,我按 count(*) 降序排序,以便最频繁出现的值为 1。

      注意 row_number() 只返回 '1' 到一行。

      所以,现在我们有

      select Name, Customer, Location, row_number() over (partition by Name, Customer order by count(*) desc) freq_name_cust
      from table1 tb_
      group by Name, Customer, Location
      

      最后一步将所有内容放在一起:

      select tab.*, tb_.Location most_freq_location
      from table1 tab
      inner join 
      (select Name, Customer, Location, row_number() over (partition by Name, Customer order by count(*) desc) freq_name_cust
       from table1 
       group by Name, Customer, Location) tb_
       on tb_.Name = tab.Name
        and tb_.Customer = tab.Customer
         and freq_name_cust = 1
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-02-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-11-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多