获取SQL中另一列的每个值的最常用值
我有一张这样的桌子:获取SQL中另一列的每个值的最常用值,sql,postgresql,greatest-n-per-group,Sql,Postgresql,Greatest N Per Group,我有一张这样的桌子: Column | Type | Modifiers ---------+------+----------- country | text | food_id | int | eaten | date | 对于每个国家,我都想得到最常吃的食物。我能想到的最好办法(我正在使用postgres)是: 在最后一个语句中,需要GROUP BY和max()来打破两种不同食物计数相同的关系 对于概念上简单的东西来说,这似乎需要做很多工作。有更直接的方法吗?试试
Column | Type | Modifiers
---------+------+-----------
country | text |
food_id | int |
eaten | date |
对于每个国家,我都想得到最常吃的食物。我能想到的最好办法(我正在使用postgres)是:
在最后一个语句中,需要GROUP BY和max()来打破两种不同食物计数相同的关系
对于概念上简单的东西来说,这似乎需要做很多工作。有更直接的方法吗?试试这样的方法
select country, food_id, count(*) cnt
into #tempTbl
from mytable
group by country, food_id
select country, food_id
from #tempTbl as x
where cnt =
(select max(cnt)
from mytable
where country=x.country
and food_id=x.food_id)
这可以放在一个单一的选择,但我现在没有时间去胡闹
祝你好运。以下是在没有临时表的情况下如何操作: 编辑:简化 嗯,我匆忙写了这封信,但没有检查清楚。子选择可能非常慢,但这是我能想到的最短、最简单的SQL语句。等我不那么醉的时候,我可能会说更多 附言:哦,“foo”是我桌子的名字,“food”包含食物的名字,“country”包含国家的名字。样本输出:
food | country
-----------+------------
Bratwurst | Germany
Fisch | Frankreich
我不喜欢马克斯(.)小组打破联系。。。必须有一种方法将日期合并到联接中,以某种方式任意选择最近的日期
我对这个东西的查询计划感兴趣,如果你在你的实时数据上运行它 试试这个:
select country,food_id, count(*) ne
from food f1
group by country,food_id
having count(*) = (select max(count(*))
from food f2
where country = f1.country
group by food_id)
Select Country, Food_id
From Munch T1
Where Food_id=
(Select Food_id
from Munch T2
where T1.Country= T2.Country
group by Food_id
order by count(Food_id) desc
limit 1)
group by Country, Food_id
PostgreSQL在8.4中引入了对的支持,也就是在提出这个问题的第二年。值得注意的是,今天可能会解决如下问题:
SELECT country, food_id
FROM (SELECT country, food_id, ROW_NUMBER() OVER (PARTITION BY country ORDER BY freq DESC) AS rn
FROM ( SELECT country, food_id, COUNT('x') AS freq
FROM country_foods
GROUP BY 1, 2) food_freq) ranked_food_req
WHERE rn = 1;
上述情况将打破僵局。如果你不想断绝关系,你可以用DENSE_RANK()来代替。我相信这句话能满足你的需要,而且简单明了:
select distinct on (country) country, food_id
from munch
group by country, food_id
order by country, count(*) desc
请让我知道你的想法
顺便说一句,distinct on功能仅在Postgres中可用
例如,源数据:
country | food_id | eaten
US 1 2017-1-1
US 1 2017-1-1
US 2 2017-1-1
US 3 2017-1-1
GB 3 2017-1-1
GB 3 2017-1-1
GB 2 2017-1-1
输出:
country | food_id
US 1
GB 3
现在更简单了:PostgreSQL 9.4引入了
mode()
函数:
select mode() within group (order by food_id)
from munch
group by country
返回(如user2247323的示例):
请参阅此处的文档:
我很想看看这个执行计划与临时表的对比——那些“having”子句是在select检索匹配行后计算的,对吗?看起来可能有很多额外的IO。计划中有几个完整的表扫描,是的。如果你打算在这么长时间后提出一个新的答案,我建议你在一个示例表上尝试,并发布你得到的结果。另外,请提及您正在使用的数据库服务器(mysql或其他)。distinct on功能仅在Postgres中可用,因此,我不确定您将如何在其他数据库中执行类似操作。OP正在使用Postgres,因此它似乎是合适的。我使用op建议的数据库表munch编写了这篇文章,它有三个字段:country(文本)、food_id(int)和eat(date),我认为在大多数地方都需要单引号。
select distinct on (country) country, food_id
from munch
group by country, food_id
order by country, count(*) desc
country | food_id | eaten
US 1 2017-1-1
US 1 2017-1-1
US 2 2017-1-1
US 3 2017-1-1
GB 3 2017-1-1
GB 3 2017-1-1
GB 2 2017-1-1
country | food_id
US 1
GB 3
select mode() within group (order by food_id)
from munch
group by country
country | mode
--------------
GB | 3
US | 1