【问题标题】:SQL - Using GROUP BY and MIN COUNT to return the least counted variableSQL - 使用 GROUP BY 和 MIN COUNT 返回计数最少的变量
【发布时间】:2017-07-29 19:37:16
【问题描述】:

我在使用 GROUP BYMAXCOUNT 时遇到问题。

我有 3 个表格,t1、t2、t3 包含营养数据。

  • t1 包含userid
  • t2 包含food 和食物的type。 (水果、肉类等)
  • t3记录userid每次吃东西,所以userid,food

你如何编写一个(Postgres)查询,只返回userid最少type 的食物?

我一直卡在GROUP BY 上,因为聚合会创建每种食物的组合。关于我应该如何处理这个问题的任何提示?

【问题讨论】:

  • 当您需要sql查询时,请发布一些示例数据和预期结果,并尽可能向我们展示您尝试过的内容。
  • t4 包含解决方案。
  • 你不必重新发明轮子,这是一个典型的greatest-n-per-group查询(有plenty of solutions here),只需反转运算符找到最小,而不是最大的

标签: sql postgresql count group-by min


【解决方案1】:
select userid, max(c_type) as MaxType
From (Select userid, count(type) as c_type 
from t1 inner join t3 on t1.userid = t3.userid
        inner join t2 on t2.food = t3.food
group by userid) as T
group by userid

【讨论】:

    【解决方案2】:

    如果您想要每个用户最不常吃的食物类型,首先按用户 AND 类型计算出现次数,然后您需要使用排名函数来确定哪些食物类型的次数最少。我不会费心写出所有的连接,但是这个伪代码应该会有所帮助:

    select user_id, type, type_total
    from ( select user_id, type, type_total,
           rank(type_total) over (partition by user_id, type order by type_total) rn
           from ( select user_id, type, count(t3 identifier) type_total
                  from [insert all the tables and joins here]
                  group by user_id, type ) x
           ) y
    where y.rn = 1
    

    【讨论】:

      【解决方案3】:

      此方法使用 ROW_NUMBER 窗口函数,对按类型分组的已吃食物计数进行升序排序,以确定最少吃的食物。如果有平局,将随机选择最少的一种。在发布的@htf 的解决方案中使用 RANK 将返回所有关系。

      select userid, type from (
          select t3.userid, t2.type, count(*) as eaten,
              row_number() over(partition by t3.userid order by count(t3.food) asc) AS r
          from t3 join t2 on t3.food=t2.food
          group by 1,2
      ) least
      where r=1
      

      假设你想从 t1 中得到一些东西,就像:

      select t1.name, least.type from (
          select t3.userid, t2.type, count(*) as eaten,
              row_number() over(partition by t3.userid order by count(t3.food) asc) AS r
          from t3 join t2 on t3.food=t2.food
          group by 1,2
      ) least
      join t1 on t1.userid=least.userid
      where least.r=1
      

      这是一种不使用窗口功能的方法。这种方式对吃的类型计数使用自联接来识别最少吃的食物并过滤其他更常吃的食物(添加 t1 假设你想要一些字段):

      with type_counts as (
          select t3.userid, t2.type, count(*) as eaten,
          from t3 join t2 on t3.food=t2.food
          group by 1,2
      )
      select t1.username, tc.userid, tc.type
      from type_counts tc
      inner join (select userid, min(eaten) as eaten from type_counts group by 1) mintc
          on tc.userid=mintc.userid and tc.eaten=mintc.eaten
      inner join t1 on t1.userid=tc.userid
      

      这个版本将包括最少吃的领带。

      【讨论】:

        猜你喜欢
        • 2019-03-21
        • 2013-04-06
        • 2011-04-05
        • 2012-11-20
        • 2011-04-18
        • 2021-10-07
        • 2014-04-26
        • 2018-10-26
        • 1970-01-01
        相关资源
        最近更新 更多