我在使用GROUP BY
,MAX
和COUNT
时遇到问题。
我有3个表,t1,t2,t3和营养数据。
userid
food
和type
食物。 (水果,肉等)userid
,food
你如何写一个(Postgres)查询只返回userid
和最少吃过type
的食物?
由于聚合产生了每种食物的组合,我一直卡在GROUP BY
上。关于如何处理这个问题的任何提示?
答案 0 :(得分:0)
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
答案 1 :(得分:0)
如果您想要每个用户最常吃的食物类型,首先按用户和类型计算出现次数,然后您需要使用等级函数来确定哪些食物类型具有最低计数。我不打算写出所有的连接,但这个伪代码应该有所帮助:
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
答案 2 :(得分:0)
此方法使用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
此版本将包含至少吃过的关系。