首页 文章

为每个类别选择前10条记录

提问于
浏览
169

我想在一个查询中返回每个部分的前10条记录 . 任何人都可以帮忙解决这个问题吗? Section是表中的一列 .

数据库是SQL Server 2005.我想按输入的日期返回前10名 . 部分是业务,本地和功能 . 对于一个特定日期,我只需要前(10)个业务行(最近的条目),前(10)个本地行和前(10)个特征 .

14 回答

  • 4
    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
    
  • 73

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

    UNION运算符可能适合您吗?每个部分都有一个SELECT,然后将它们组合在一起 . 猜猜它只适用于固定数量的部分 .

  • 0

    如果您使用的是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的解决方案可能对您更好 .

  • 4

    问)从每个组中查找TOP 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
    

    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行 .


  • 10

    虽然问题是关于SQL Server 2005的,但是大多数人都已经开始了,如果他们确实发现了这个问题,那么在其他情况下,首选答案是什么?using CROSS APPLY as illustrated in this blog post .

    SELECT *
    FROM t
    CROSS APPLY (
      SELECT TOP 10 u.*
      FROM u
      WHERE u.t_id = t.t_id
      ORDER BY u.something DESC
    ) u
    

    此查询涉及2个表 . OP的查询仅涉及1个表,在这种情况下,基于窗口函数的解决方案可能更有效 .

  • 8

    如果您知道这些部分是什么,您可以:

    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
    
  • 4

    如果要生成按部分分组的输出,则只显示每个部分的前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;
    

    Build :

    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';
    
  • 22

    我是这样做的:

    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;
    

    update: GROUP BY的这个示例仅适用于MySQL和SQLite,因为这些数据库比关于GROUP BY的标准SQL更宽松 . 大多数SQL实现要求select-list中不属于聚合表达式的所有列也在GROUP BY中 .

  • 1

    这适用于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
    
  • 31

    尝试了以下内容,它也与关系一起工作 .

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

    在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
    
  • 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问题 .

  • 182

    如果我们使用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;
    

相关问题