Sql 尝试在列上分组,同时按顺序选择所有其他信息
我在构造使用以下条件的查询时遇到了一些问题:Sql 尝试在列上分组,同时按顺序选择所有其他信息,sql,postgresql,group-by,greatest-n-per-group,Sql,Postgresql,Group By,Greatest N Per Group,我在构造使用以下条件的查询时遇到了一些问题: 与组织匹配 按分数(desc)排序,然后按句柄(asc)排序 按类型分组 所以这个查询是我的出发点: select * from social_media_handles where org = '00000001' order by score desc, handle asc; 这将给我以下数据。。。然后我需要按类型进行分组,这样我只需要拿出最匹配的社交媒体手柄 org | ha
select * from social_media_handles where org = '00000001' order by score desc, handle asc;
这将给我以下数据。。。然后我需要按类型进行分组,这样我只需要拿出最匹配的社交媒体手柄
org | handle | url | type | score | dataset_date
----------+---------------------------------------------------------------+-----------------------------------------+----------+-----------------+--------------
00000001 | boathousesw15 | http://www.boathouseputney.co.uk | twitter | 500111972000056 | 2013-10-15
00000001 | aspall | http://www.boathouseputney.co.uk | twitter | 500111972000018 | 2013-10-15
00000001 | nathansloane | http://www.boathouseputney.co.uk | twitter | 500111972000018 | 2013-10-15
00000001 | youngspubs | http://www.boathouseputney.co.uk | twitter | 500111972000018 | 2013-10-15
00000001 | pages/the-boathouse-putney/153429008029137 | http://www.boathouseputney.co.uk | facebook | 500111972000011 | 2013-10-15
00000001 | putneysocial | http://www.boathouseputney.co.uk | twitter | 500111972000009 | 2013-10-15
00000001 | theexchangesw15 | http://www.boathouseputney.co.uk | twitter | 500111972000009 | 2013-10-15
00000001 | youngspubs | http://www.youngshotels.co.uk | twitter | 500111970000016 | 2013-10-15
预期产量
org | handle | url | type | score | dataset_date
----------+---------------------------------------------------------------+-----------------------------------------+----------+-----------------+--------------
00000001 | boathousesw15 | http://www.boathouseputney.co.uk | twitter | 500111972000056 | 2013-10-15
00000001 | pages/the-boathouse-putney/153429008029137 | http://www.boathouseputney.co.uk | facebook | 500111972000011 | 2013-10-15
我试过按分组、不同的
和子查询,但运气不太好。这个问题有什么规律吗
我正在使用Postgres,并在上使用distinct解决了这个问题,但我正在寻找一个与不同供应商兼容的版本。有几种方法可以做到这一点,所有方法都基于两个想法。第一个想法是为每种类型获取具有最大分数的记录集,然后将原始表连接到此记录集。第二个想法是,如果你有排名函数,你只需在每个
类型中使用行编号()
,然后用行编号>1
过滤掉所有记录
第一个想法可以这样写:
select *
from Table1 as T
where
exists (
select 1
from Table1 as TT
where TT.type = T.type
having max(TT.score) = T.score
)
或
如果你有排名功能,那么你也可以使用第二个想法:
with cte as (
select *, row_number() over(partition by type order by score desc) as rn
from Table1
)
select *
from cte
where rn = 1
您可以轻松地用子查询替换公共表表达式:
select *
from (
select *, row_number() over(partition by type order by score desc) as rn
from Table1
) as a
where rn = 1
更新
有一件事需要提及——如果您有多条记录,例如,score=500111972000056,type=twitter
,那么第一个解决方案将为type='twitter'返回多条记录,而第二个解决方案为type='twitter'返回任意一行
另外,我忘了提到第三个想法(参见nice@Bill Karwin答案)。我只想在这里加上:
select *
from Table1 as T
where
not exists (
select *
from Table1 as TT
where TT.type = T.type and TT.score > T.score
);
这个问题在SO上经常出现,并且通常会给它一个标签(在您的例子中,n=1)
以下是几个在MySQL中可用的常见解决方案:
SELECT h.*
FROM social_media_handles AS h
JOIN (
SELECT type, MAX(score) AS score
FROM social_media_handles WHERE org = '00000001'
GROUP BY type) AS maxh USING (type, score)
WHERE org = '00000001'
ORDER BY score DESC, handle ASC;
第二种解决方案不使用子查询或分组依据。它尝试将一行h1与一个假设行h1进行匹配,该假设行h1具有相同的类型
和组织
,但具有更高的分数
。如果不存在得分较高的行h2,则h1必须是得分最高的行
SELECT h1.*
FROM social_media_handles AS h1
LEFT OUTER JOIN social_media_handles AS h2
ON h1.type = h2.type AND h1.org = h2.org AND h1.score < h2.score
WHERE h1.org = '00000001'
AND h2.score IS NULL
ORDER BY h1.score DESC, h1.handle DESC;
选择h1*
来自社交媒体,作为h1处理
左外联接社交媒体句柄为h2
在h1.type=h2.type和h1.org=h2.org和h1.score
哪种解决方案最快?视情况而定。根据数据集的大小、不同类型的数量等,我让这两种方法都能更好地工作。因此,您应该测试这两种解决方案,看看哪些方法更适合您的情况
@Roman Pekar展示的CTE解决方案也适用于支持CTE语法的RDBMS。这些包括PostgreSQL、Oracle、MicrosoftSQLServer、IBMDB2和其他一些
MySQL和SQLite是唯一广泛使用的仍然不支持CTE语法的数据库。我不明白我们是如何定义顶级匹配的社交媒体句柄的。
@草莓,每个type
在score
列中得分最高的人。啊哈,好吧,假设Roman Pekar的第二个解决方案对postgres有效(有一个小的修正),那么我猜那将是最快的。@草莓,我想这取决于你有10000条type='facebook'的记录,并且你有一个合适的索引,然后第一个是fasterOK——我不知道postgres,所以我不能对这种答案发表评论。第二个答案是+1,提到没有银弹:),我忘了没有银弹。也许我应该补充我的答案,如果原始版本中存在重复版本,那么解决方案可能会有不同的效果table@RomanPekar,是的,如果您有多个行,每个组都有最大分数,那么结果中会有多行。这就是CTE解决方案的最佳方式。为让我意识到每个组的最大n值而干杯。这件事我得多调查一下。
SELECT h1.*
FROM social_media_handles AS h1
LEFT OUTER JOIN social_media_handles AS h2
ON h1.type = h2.type AND h1.org = h2.org AND h1.score < h2.score
WHERE h1.org = '00000001'
AND h2.score IS NULL
ORDER BY h1.score DESC, h1.handle DESC;