我想在一个查询中返回每个部分的前10条记录。有人能帮我做吗?Section是表中的列之一。

数据库为SQL Server 2005。我想按输入的日期返回前10名。部分包括业务、本地和特性。对于一个特定的日期,我只想要顶部(10)业务行(最近的条目)、顶部(10)本地行和顶部(10)特性。


当前回答

如果你正在使用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的解决方案可能更适合你。

其他回答

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

如果你正在使用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 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 Server 2005的,但大多数人已经继续前进了,如果他们确实发现了这个问题,在其他情况下首选的答案可能是使用CROSS APPLY,就像这篇博客文章中所说明的那样。

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

该查询涉及两个表。OP的查询只涉及1个表,在这种情况下,基于窗口函数的解决方案可能更有效。

我知道这个帖子有点老了,但我刚刚遇到了一个类似的问题(从每个类别中选择最新的文章),这是我想出的解决方案:

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问题。