Sql 为每个类别选择前10项记录
我想在一个查询中返回每个部分的前10条记录。有人能帮忙做这件事吗?节是表中的一列Sql 为每个类别选择前10项记录,sql,sql-server,sql-server-2005,greatest-n-per-group,Sql,Sql Server,Sql Server 2005,Greatest N Per Group,我想在一个查询中返回每个部分的前10条记录。有人能帮忙做这件事吗?节是表中的一列 数据库是SQLServer2005。我想按输入的日期返回前10名。部分包括业务、本地和功能。对于某个特定日期,我只需要前10个业务行、最近的条目、前10个本地行和前10个功能。操作员是否可以为您工作?为每个部分选择一个,然后将它们合并在一起。不过,我猜它只适用于固定数量的部分。这在SQL Server 2005上起作用,经过编辑以反映您的澄清: select * from Things t where t.Thin
数据库是SQLServer2005。我想按输入的日期返回前10名。部分包括业务、本地和功能。对于某个特定日期,我只需要前10个业务行、最近的条目、前10个本地行和前10个功能。操作员是否可以为您工作?为每个部分选择一个,然后将它们合并在一起。不过,我猜它只适用于固定数量的部分。这在SQL Server 2005上起作用,经过编辑以反映您的澄清:
select *
from Things t
where t.ThingID in (
select top 10 ThingID
from Things tt
where tt.Section = t.Section and tt.ThingDate = @Date
order by tt.DateEntered desc
)
and t.ThingDate = @Date
order by Section, DateEntered desc
如果您知道这些部分是什么,您可以执行以下操作:
select top 10 * from table where section=1
union
select top 10 * from table where section=2
union
select top 10 * from table where section=3
如果您使用的是SQL 2005,则可以执行以下操作
SELECT rs.Field1,rs.Field2
FROM (
SELECT Field1,Field2, Rank()
over (Partition BY Section
ORDER BY RankCriteria DESC ) AS Rank
FROM table
) rs WHERE Rank <= 10
如果您的RankCriteria有联系,那么您可以返回超过10行,Matt的解决方案可能更适合您。我这样做:
SELECT a.* FROM articles AS a
LEFT JOIN articles AS a2
ON a.section = a2.section AND a.article_date <= a2.article_date
GROUP BY a.article_id
HAVING COUNT(*) <= 10;
更新:这个GROUPBY示例仅适用于MySQL和SQLite,因为这些数据库比标准SQL对GROUPBY的权限更大。大多数SQL实现都要求选择列表中不属于聚合表达式的所有列也在GROUP BY中。我知道此线程有点旧,但我刚刚遇到了类似的问题,请从每个类别中选择最新的文章,这就是我提出的解决方案:
WITH [TopCategoryArticles] AS (
SELECT
[ArticleID],
ROW_NUMBER() OVER (
PARTITION BY [ArticleCategoryID]
ORDER BY [ArticleDate] DESC
) AS [Order]
FROM [dbo].[Articles]
)
SELECT [Articles].*
FROM
[TopCategoryArticles] LEFT JOIN
[dbo].[Articles] ON
[TopCategoryArticles].[ArticleID] = [Articles].[ArticleID]
WHERE [TopCategoryArticles].[Order] = 1
这与Darrel的解决方案非常相似,但克服了可能返回比预期更多行的排名问题。Q从每个组中查找前X条记录Oracle
SQL> select * from emp e
2 where e.empno in (select d.empno from emp d
3 where d.deptno=e.deptno and rownum<3)
4 order by deptno
5 ;
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
选择6行
在T-SQL中,我将执行以下操作:
WITH TOPTEN AS (
SELECT *, ROW_NUMBER()
over (
PARTITION BY [group_by_field]
order by [prioritise_field]
) AS RowNo
FROM [table_name]
)
SELECT * FROM TOPTEN WHERE RowNo <= 10
如果要生成按节分组的输出,则仅显示每个节的前n条记录,如下所示:
SECTION SUBSECTION
deer American Elk/Wapiti
deer Chinese Water Deer
dog Cocker Spaniel
dog German Shephard
horse Appaloosa
horse Morgan
…那么下面的内容应该可以非常通用地用于所有SQL数据库。如果您想要前10名,只需将查询末尾的2改为10即可
select
x1.section
, x1.subsection
from example x1
where
(
select count(*)
from example x2
where x2.section = x1.section
and x2.subsection <= x1.subsection
) <= 2
order by section, subsection;
如果我们使用SQL Server>=2005,那么我们只能通过一个选择来解决该任务:
您可以尝试这种方法。 此查询返回每个国家人口最多的10个城市
SELECT city, country, population
FROM
(SELECT city, country, population,
@country_rank := IF(@current_country = country, @country_rank + 1, 1) AS country_rank,
@current_country := country
FROM cities
ORDER BY country, population DESC
) ranked
WHERE country_rank <= 10;
尝试了以下方法,它也可以与领带一起使用
SELECT rs.Field1,rs.Field2
FROM (
SELECT Field1,Field2, ROW_NUMBER()
OVER (Partition BY Section
ORDER BY RankCriteria DESC ) AS Rank
FROM table
) rs WHERE Rank <= 10
虽然这个问题是关于SQLServer2005的,但大多数人都已经离开了,如果他们确实发现了这个问题,那么在其他情况下,什么可能是首选答案呢 挑选* 从t 交叉应用 选择前10名* 来自美国 其中u.t_id=t.t_id 由美国订购 U
此查询涉及2个表。OP的查询只涉及1个表,在这种情况下,基于窗口函数的解决方案可能更有效。但这不适用于节为空的行。您需要说明tt.Section为null,t.Section为null或tt.Section=t.Section这将是最简单的方法。但如果您有150个类别,或者类别按天、周等变化,则这将是无效的。当然,但请引用OP:Sections是业务、本地和功能。如果你有三个静态类别,这是最好的方法。如果你真的想要前10名,把它改为RowNumber而不是Rank。这样就没有关系了。这是可行的,但请注意,如果没有索引,第一个键是RankCriteria,则查询计划器可能会将秩转换为完整表排序。在这种情况下,您可以选择不同的路段并交叉应用,以选择RankCriteria desc订购的前10名,从而获得更好的里程数。回答得很好!几乎完全满足了我的需要。我最终选择了稠密的等级,在编号上没有任何差距+1@Facbed这只是表上的一个别名。对于任何使用Sql Server的人来说,Mike L提到的RowNumber函数就是ROW_NUMBER。这样行吗?我很肯定您会发现a.somecolumn在选择列表中无效,因为它不包含在聚合函数中,也不包含在除article_id之外的项目中的每一列的group by子句中。您应该能够包含功能上依赖于group by中命名的列的其他列。功能上不相关的列是不明确的。但你是对的,这取决于RDBMS的实现。它在MySQL中工作,但在InterBase/Firebird中IIRC失败。如果某个区段的前11条记录都有相同的日期,这是否有效?它们的计数都是11,结果将是一个空集。不,如果它们都有相同的日期,你需要有一些打破关系的方法。例如,请参阅。@carlosgg,如果文章与节有多对多关系,则需要有一个交集表来将文章映射到它们的节。然后,您的查询必须连接到m2m关系的交叉表,并按项目id和节分组。这应该让你开始,但我不会在评论中写出整个解决方案。请对你的解决方案进行更多描述。REFERE:CTE的select查询是否可以包含where子句?@toha是的,尽管您在T-SQL中说这适用于任何实现行号的数据库
作用例如,我在SQLite中使用了这个解决方案,它也适用于PostgresSQL。我只需要使用order by[Prioritization_field]desc+1,我喜欢这个简单的解决方案,但是你能解释一下在order by子句中使用top 1如何处理返回0或1的case语句吗?top 1在这里处理TIES。使用TIES意味着,当ORDER BY=0时,SELECT将获取此记录,因为TOP 1和所有其他具有ORDER BY=0的记录,因为使用TIES,当我只需要每个部分的第一条记录时,这不起作用。它消除了所有具有1条以上记录的分区组。我试图替换@nils,因为只有三个部分值:鹿、狗和马。如果将查询更改为,但当我尝试运行查询时,它会消除所有内容,因为所有内容的计数都大于等于1。它没有为每个部分保留第1小节。你能试着运行@nils的查询吗?嗨,我确实从脚本中重新创建了这个小测试数据库,并使用它运行了查询,它在mysql中非常适合我。我改变了一个问题,不知道他为什么用这个问题是关于SQL Server,而不是Oracle。什么是别名为“m”的表?@Chalky它的拼写错误,应该是r。修好了,很有魅力。非常感谢。如果输入了一条领带怎么办?@Yiping未定义。任何争吵都可能获胜。这取决于许多情况,可能会有所不同。您可以通过添加更多列使订单更加具体,例如按r.DateEntered、r.ID排序,但这取决于您的特定任务。为什么要使用CTE先生?它能减少内存消耗吗?@toha因为CTE更简单,更容易理解,这是一个很好的答案!!它可以通过使用内部连接而不是左连接进行优化,因为如果没有相应的文章记录,就永远不会有TopCategoryArticles的记录。这些答案对你有用吗?我想我们永远也不会知道……已经过去12年了,我们不知道这些答案是否有效。例如,当我们有一个记录了一个国家9个相同人口的表时,这个解决方案不会通过测试用例它返回null,而不是按顺序返回所有9条可用记录。有任何解决此问题的建议吗?您好,在我在视图中添加聚合度量之前,查询对我来说很有效。从中选择rs.Field1、rs.Field2、rs.measure,从表rs中选择Field1、Field2、sumcastmeasure as INT overpartition by section as agg_measure、ROW_NUMBER OVER Partition by section ORDER by agg_measure DESC作为秩,其中秩
create table example ( id int, section varchar(25), subsection varchar(25) );
insert into example select 0, 'dog', 'Labrador Retriever';
insert into example select 1, 'deer', 'Whitetail';
insert into example select 2, 'horse', 'Morgan';
insert into example select 3, 'horse', 'Tarpan';
insert into example select 4, 'deer', 'Row';
insert into example select 5, 'horse', 'Appaloosa';
insert into example select 6, 'dog', 'German Shephard';
insert into example select 7, 'horse', 'Thoroughbred';
insert into example select 8, 'dog', 'Mutt';
insert into example select 9, 'horse', 'Welara Pony';
insert into example select 10, 'dog', 'Cocker Spaniel';
insert into example select 11, 'deer', 'American Elk/Wapiti';
insert into example select 12, 'horse', 'Shetland Pony';
insert into example select 13, 'deer', 'Chinese Water Deer';
insert into example select 14, 'deer', 'Fallow';
declare @t table (
Id int ,
Section int,
Moment date
);
insert into @t values
( 1 , 1 , '2014-01-01'),
( 2 , 1 , '2014-01-02'),
( 3 , 1 , '2014-01-03'),
( 4 , 1 , '2014-01-04'),
( 5 , 1 , '2014-01-05'),
( 6 , 2 , '2014-02-06'),
( 7 , 2 , '2014-02-07'),
( 8 , 2 , '2014-02-08'),
( 9 , 2 , '2014-02-09'),
( 10 , 2 , '2014-02-10'),
( 11 , 3 , '2014-03-11'),
( 12 , 3 , '2014-03-12'),
( 13 , 3 , '2014-03-13'),
( 14 , 3 , '2014-03-14'),
( 15 , 3 , '2014-03-15');
-- TWO earliest records in each Section
select top 1 with ties
Id, Section, Moment
from
@t
order by
case
when row_number() over(partition by Section order by Moment) <= 2
then 0
else 1
end;
-- THREE earliest records in each Section
select top 1 with ties
Id, Section, Moment
from
@t
order by
case
when row_number() over(partition by Section order by Moment) <= 3
then 0
else 1
end;
-- three LATEST records in each Section
select top 1 with ties
Id, Section, Moment
from
@t
order by
case
when row_number() over(partition by Section order by Moment desc) <= 3
then 0
else 1
end;
SELECT city, country, population
FROM
(SELECT city, country, population,
@country_rank := IF(@current_country = country, @country_rank + 1, 1) AS country_rank,
@current_country := country
FROM cities
ORDER BY country, population DESC
) ranked
WHERE country_rank <= 10;
SELECT rs.Field1,rs.Field2
FROM (
SELECT Field1,Field2, ROW_NUMBER()
OVER (Partition BY Section
ORDER BY RankCriteria DESC ) AS Rank
FROM table
) rs WHERE Rank <= 10