2014-10-16 72 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