2014-10-16 76 views
1

我不确定标题会是什么,所以事先要道歉。SELECT语句如何按行号返回不同的组?

比方说,我有一个简单的TSQL语句,看起来像SELECT City from Cities。这将返回一个结果有26行:

City 
New York 
Los Angeles 
Chicago 
Houston 
Philadelphia 
Phoenix 
San Antonio 
San Diego 
Dallas 
San Jose 
Austin 
Indianapolis 
Jacksonville 
San Francisco 
Columbus 
Charlotte 
Fort Worth 
El Paso 
Memphis 
Seattle 
Denver 
Washington 
Boston 
Nashville 
Baltimore 
Oklahoma City 

现在,让我们说,我想这个结果分为3组,每组10行。换句话说,当我运行查询时,结果将显示三个“不同的”行集合,前两行包含10行,最后一行包含6个余数。就像我一次运行这3个查询:a top(10),a middle(10) and a 剩余部分。如果我要从.Net应用程序运行此查询,则dataset将具有3 datatables

这里的问题是没有什么我可以用来分组数据。即使我做了,我也不想。我想指定这个查询将返回多少个数据表以及每个数据表有多少行。

+0

哪个版本的SQL Server? – DavidG 2014-10-16 20:08:15

回答

1

我想你想使用row-number()和一些算术:

select ((seqnum - 1)/10) as grp, city 
from (select city, row_number() over (order by (select NULL)) as seqnum 
     from cities 
    ) c; 

注意顺序不能保证。您确实需要一个特定的列来指定顺序,因为SQL表代表无序集。

编辑:

目前尚不清楚你想要做什么。这将行分成10个组,这似乎是你想要做的。当然,这只返回一个结果集 - 任何SQL查询只返回一个结果集。

+0

这不会将它们返回给单独的结果集。 – Jeff 2014-10-16 20:24:06

+0

@jeff。 。 。它将它们分配给单独的组ID,这似乎是对该问题的非常合理的回应。 – 2014-10-16 20:27:56

+0

“我想指定这个查询将返回多少个数据表以及每个数据表有多少行” - 我不同意。我会删除我的-1,因为我认为这是解决类似问题的好方法。除非我不能编辑=/ – Jeff 2014-10-16 20:33:11

1

如果您正在使用SQL Server 2012或以上,你可以使用OFFSET/FETCH关键字:

因此,这将让你的前10个城市:

SELECT City 
FROM Cities 
ORDER BY City 
    OFFSET 0 ROWS 
    FETCH NEXT 10 ROWS ONLY 

,这将获得下一个10:

SELECT City 
FROM Cities 
ORDER BY City 
    OFFSET 10 ROWS 
    FETCH NEXT 10 ROWS ONLY 

你也可以通过使用变量替换这些数字:

DECLARE @PageSize INT = 10 
DECLARE @PageNumber INT = 5 

SELECT City 
FROM Cities 
ORDER BY City 
    OFFSET @PageNumber * @PageSize ROWS 
    FETCH NEXT @PageSize ROWS ONLY 
0

您需要一个Cursor或者一个WHILE loop。当我在大约30分钟的休息时间之后,我会充实代码,但现在足以说您需要将它与窗口函数结合以将该组分成10个组,然后选择每个组1 ×1。

Summat这样的:

declare @paginator int = 0 
declare @totalPages int = (select count(*) from cities)/10 + 1 

while @paginator <= @totalPages 
begin 
    select city 
    from (
     select 
      city, 
      row_number() over (order by city) as rownumber 
     from cities) 
    where rownumber <= @paginator * 10 + 10 
    AND rownumber > @paginator * 10 

    set @paginator = @paginator + 1 
end 
-1

没有什么原产于SQL服务器*的任何版本,可以让你说“返回基于以下标准N> 1点的数据集”在一个单一的T-SQL 声明。根据(迄今为止的3)其他答复,你必须建立N个不同的,精心构造的查询。

(好吧,我还没有与2012年或2014年合作过,但是如果他们确实有这样的语法,我会非常惊讶 - 而且低估了。)

+0

现在有四个答案,但是一个是自我删除的。 – 2014-10-16 20:20:44

+0

不正确。你可以构造循环来做到这一点。 – Jeff 2014-10-16 20:21:20

+0

OFFSET/FETCH,这是一个赢家!但我不会downvote :) – DavidG 2014-10-16 20:22:06

0

我认为最好的解决方案应该是动态查询中的循环和偏移子句的组合。它有:

create table city(
    name varchar(100) 
) 

insert into city values ('City') 
insert into city values ('New York') 
insert into city values ('Los Angeles') 
insert into city values ('Chicago') 
insert into city values ('Houston') 
insert into city values ('Philadelphia') 
insert into city values ('Phoenix') 
insert into city values ('San Antonio') 
insert into city values ('San Diego') 
insert into city values ('Dallas') 
insert into city values ('San Jose') 
insert into city values ('Austin') 
insert into city values ('Indianapolis') 
insert into city values ('Jacksonville') 
insert into city values ('San Francisco') 
insert into city values ('Columbus') 
insert into city values ('Charlotte') 
insert into city values ('Fort Worth') 
insert into city values ('El Paso') 
insert into city values ('Memphis') 
insert into city values ('Seattle') 
insert into city values ('Denver') 
insert into city values ('Washington') 
insert into city values ('Boston') 
insert into city values ('Nashville') 
insert into city values ('Baltimore') 
insert into city values ('Oklahoma City') 

DECLARE @TOTAL INT 
     ,@GROUP INT 
     ,@STR VARCHAR(10) 

SELECT 
    @GROUP=0 
    ,@TOTAL=COUNT(*) 
FROM CITY 

WHILE @GROUP < @TOTAL 
BEGIN 
    SELECT @STR=CAST(@GROUP AS VARCHAR(10)) 

    EXEC('SELECT Name '+ 
     'FROM City '+ 
     ' OFFSET '[email protected]+' ROWS '+ 
     ' FETCH NEXT 10 ROWS ONLY') 

    SELECT @GROUP += 10; 
END 

希望它有帮助!

+0

我觉得这个解决方案很有趣,因为如果你为城市表添加更多的值,就不需要改变查询,它会根据需要生成多个集合。 – 2014-10-17 14:31:40