2008-10-07 81 views
142

我想在一个查询中返回每个部分的前10条记录。任何人都可以帮助如何做到这一点?部分是表中的一列。为每个类别选择前10条记录

数据库是SQL Server 2005.我想按输入日期返回前10位。部分是商业,本地和功能。对于某个特定日期,我只需要顶部(10)业务行(最新条目),顶部(10)本地行和顶部(10)功能。

+0

这些答案有帮助吗? – 2017-12-01 20:55:58

回答

4

可能是UNION运营商为您工作?每个部分都有一个SELECT,然后将它们联合在一起。猜猜它只能用于固定数量的部分。

28

这工作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 
+2

但是,对于Section为空的行,这不起作用。你需要说“哪里(tt.Section为空,t.Section为空)或tt.Section = t.Section” – 2008-10-07 02:11:30

9

如果你知道是什么部分是,你可以这样做:

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 
+3

这将是最简单的方法。 – 2008-10-07 02:15:33

+1

但是,如果您有150个类别,或者如果类别按日,周等变化,这将是低效的。 – 2017-09-08 15:26:03

+0

当然,但是引用OP:“部分是业务,本地和功能”。如果你有三个静态类别,这是最好的方式。 – Blorgbeard 2017-09-08 15:31:08

166

如果您正在使用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有关系,那么你可能会返回超过1 0行和马特的解决方案可能对你更好。

+25

如果您真的只想要前10名,请将其更改为RowNumber()而不是Rank()。没有关系。 – 2008-10-07 03:26:04

+3

这是有效的,但请注意,如果没有* first * key是RankCriteria的索引,rank()可能会被查询规划器转换为整个表的排序。在这种情况下,您可以选择不同的部分并交叉申请挑选RankCriteria desc订购的前10名。 – 2013-02-13 09:42:24

+0

伟大的答案!几乎正是我所需要的。我结束了`DENSE_RANK`的编号没有任何差距。 +1 – 2013-03-21 23:33:55

15

我做这种方式:

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; 

更新: BY在MySQL和SQLite的唯一作品本组的例子,因为这些数据库是不是把GROUP BY标准SQL更加宽容。大多数SQL实现要求选择列表中不属于聚合表达式的所有列也位于GROUP BY中。

8

我知道这个线程是有点有点老,但我只是碰到了类似的问题(请从每个类别的最新文章),这是我想出了解决方案:

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的解决方案非常相似,但克服了RANK问题,可能会返回比预期更多的行。

4

Q)从每个组(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 

7782 CLARK  MANAGER   7839 09-JUN-81  2450     10 
    7839 KING  PRESIDENT   17-NOV-81  5000     10 
    7369 SMITH  CLERK   7902 17-DEC-80  800     20 
    7566 JONES  MANAGER   7839 02-APR-81  2975     20 
    7499 ALLEN  SALESMAN  7698 20-FEB-81  1600  300   30 
    7521 WARD  SALESMAN  7698 22-FEB-81  1250  500   30 

6行查找TOP X记录。


18
SELECT r.* 
FROM 
(
    SELECT 
     r.*, 
     ROW_NUMBER() OVER(PARTITION BY r.[SectionID] ORDER BY r.[DateEntered] DESC) rn 
    FROM [Records] r 
) r 
WHERE r.rn <= 10 
ORDER BY r.[DateEntered] DESC 
57

在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 
3

如果你想制作的部分进行分组输出,从每一节像这样只显示前ñ记录:

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; 

要设置:

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'; 
5

如果我们使用SQL Server> = 2005,那么我们就可以解决的任务有一个选择只:

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; 
0

你可以试试这种方法。 此查询返回每个国家/地区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; 
2

试过以下,它也用于关系。

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