SQL Server SELECT LAST N Rows


139

これは既知の質問ですが、私が見つけた最良の解決策は次のようなものです:

SELECT TOP N *
FROM MyTable
ORDER BY Id DESC

行の多いテーブルがあります。時間がかかるため、このクエリを使用することはできません。では、ORDER BYを使用せずに最後のN行を選択するにはどうすればよいですか?

編集

この質問の重複した質問で申し訳ありません


「最後のN」とはどういう意味ですか?順序がなければ、「最後のN」はあまり意味がありません。「最後のNを挿入する」という意味の場合は、SQL Serverに依存してそれを提供することはできません。ORDERBY句を使用する必要があります。
Daniel Renshaw、

@Daniel Renshaw:SQL Serverにすべてのテーブルを注文することを強制せずに、テーブルの最後のNは非常に遅くなる
Diego

あなたの質問の問合せではある最良の方法。idインデックスが作成されている場合は、そのインデックスを逆方向にスキャンし、最初の5行の後で停止します。インデックスが作成されていない場合は、TOP N並べ替えを行う必要があります。これは他のどの方法よりも悪くなることはありません。テーブル全体を並べ替えることはありません(テーブル全体をスキャンする必要があります)
Martin Smith

回答:


38

ROW NUMBER BY PARTITION機能を使用して行うこともできます。良い例がここにあります

NorthwindデータベースのOrdersテーブルを使用しています...次に、従業員5が行った最後の5つの注文を取得します。

SELECT ORDERID, CUSTOMERID, OrderDate
FROM
(
    SELECT ROW_NUMBER() OVER (PARTITION BY EmployeeID ORDER BY OrderDate DESC) AS OrderedDate,*
    FROM Orders
) as ordlist

WHERE ordlist.EmployeeID = 5
AND ordlist.OrderedDate <= 5

1
ROW NUMBER BY PARTITION機能もソートを使用します。各レコードに行番号を割り当てるには、テーブルをソートする必要があります...
Sadhir

これは本当ですが、ある種の性質がないとこれは単に機能しません。最善の解決策は、ヒットする主要な列にインデックスを付け、上記のクエリのようなもので実行することです。
JonVD 2010年

101

次のSQLを使用して、SQLサーバーに最後のN行を選択させることができます。

select * from tbl_name order by id desc limit N;

2
バージョンの互換性はどうですか?
Fractaliste 2014

63
これはSQL Serverでは機能しません。MySQL、PostgreSQL、SQLiteの機能のようです。
Tim Friesen、2014年

3
列挙されているすべての製品は、明らかにSQLサーバーです。MS SQLサーバーについて話したい場合は、それに名前を付けませんか?
gena2x 2016年

4
混乱しています。「ORDER BYを使用せずに」選択クエリを作成する方法を質問すると、回答の選択クエリに「order by」が含まれます。これは、「order by」のない「order by」のようなものですか?
Robert Sinclair

5
@ gena2xこの質問はSQL Serverでタグ付けされています。このタグは、Microsoft SQL Serverを参照しています。
マーティンスミス

51

JonVDのコードをテストしましたが、6秒と非常に遅いことがわかりました。

このコードは0秒かかりました。

SELECT TOP(5) ORDERID, CUSTOMERID, OrderDate    
FROM Orders where EmployeeID=5    
Order By OrderDate DESC

4
行はいくつですか?非常に遅くなる可能性のある多くの行がある場合
Diego

@Diegoなぜですか?OrderDateインデックスが作成されている場合、クエリの最初または最後の N行を選択することは、基本的に同じくらい高速です。OrderDate挿入された順序とよく相関する可能性があることはわかっていますが、それはせいぜい副作用であり、それでもテーブルスキャンが必要です。(そして、それがOP が彼らの質問のより良い言い回しのあるものとしてつまりソートなしで指すものに答えるとは思わない)
ruffin

1
@Diego-なぜこれがあなたが受け入れた答えよりも遅いと信じているのですか?
マーティン・スミス

2
これにより、行が上下逆に返されます。その後、元の注文に戻すには、注文者が注文し直す必要があります。
マーク

15

テーブルから最後の行数を選択する場合。

構文は次のようになります

 select * from table_name except select top 
 (numbers of rows - how many rows you want)* from table_name

これらのステートメントは機能しますが、異なる方法です。君たちありがとう。

 select * from Products except select top (77-10) * from Products

このようにして、最後の10行を取得できますが、順序は降順で表示されます

select top 10 * from products
 order by productId desc 

 select * from products
 where productid in (select top 10 productID from products)
 order by productID desc

 select * from products where productID not in 
 (select top((select COUNT(*) from products ) -10 )productID from products)

7

非常に一般的な方法で、SQLサーバーをサポートするためにここにあります

SELECT TOP(N) *
FROM tbl_name
ORDER BY tbl_id DESC

パフォーマンスに関しては悪くありません(サーバーマシンで10,000レコードを超える場合は1秒未満)


1
よく、10000レコードはパフォーマンスについて気にする必要があるものではありません。何百万ものレコードについて話し始めると、パフォーマンスについて考えることができるようになります
Dom84

6

「Id」はインデックス化されていますか?そうでない場合は、それを行うことが重要です(すでにインデックスが作成されていると思います)。

また、すべての列を返す必要がありますか?ID列のインデックスで十分に対応できる小さな列のサブセットのみが実際に必要な場合は、速度が大幅に向上する可能性があります。たとえば、ID列にNONCLUSTEREDインデックスがあり、他にない場合インデックスに含まれるフィールドの場合、クラスター化されたインデックスでルックアップを実行して残りの列を実際に返す必要があり、クエリのコストの多くを占める可能性があります。それがCLUSTEREDインデックス、またはクエリで返す他のすべてのフィールドを含むNONCLUSTEREDインデックスである場合は、問題ありません。


6

最初に、ほとんどのレコード数を取得します

 Declare @TableRowsCount Int
 select @TableRowsCount= COUNT(*) from <Your_Table>

その後 :

SQL Server 2012では

SELECT *
FROM  <Your_Table> As L
ORDER BY L.<your Field>
OFFSET <@TableRowsCount-@N> ROWS
FETCH NEXT @N ROWS ONLY;

SQL Server 2008では

SELECT *
FROM 
(
SELECT ROW_NUMBER() OVER(ORDER BY ID) AS sequencenumber, *
FROM  <Your_Table>
    Order By <your Field>
) AS TempTable
WHERE sequencenumber > @TableRowsCount-@N 

4

order byこれは、なしで試すことができるものですが、各行が一意である必要があると思います。 Nは必要なL行数、はテーブルの行数です。

select * from tbl_name except select top L-N * from tbl_name

前述のように、返される行は定義されていません。

編集:これは実際には遅い犬です。本当に価値がありません。


4
select * from (select top 6 * from vwTable order by Hours desc) T order by Hours

2

このクエリは最後のN行を正しい順序で返しますが、パフォーマンスは低くなります

select *
from (
    select top N *
    from TableName t
    order by t.[Id] desc
) as temp
order by temp.[Id]

2

クエリの最後でordercを指定したdescを使用して、最後の値を取得します。


1

これは質問にぴったりとは合いませんが…

OFFSET句

このOFFSET number句を使用すると、複数の行をスキップして、その後に行を返すことができます。

そのドキュメントリンクはPostgresへのリンクです。これがSybase / MS SQL Serverに適用されるかどうかはわかりません。


1
DECLARE @MYVAR  NVARCHAR(100)
DECLARE @step  int
SET @step = 0;


DECLARE MYTESTCURSOR CURSOR
DYNAMIC 
FOR
SELECT col FROM [dbo].[table]
OPEN MYTESTCURSOR
FETCH LAST FROM MYTESTCURSOR INTO @MYVAR
print @MYVAR;


WHILE @step < 10
BEGIN   
    FETCH PRIOR FROM MYTESTCURSOR INTO @MYVAR
        print @MYVAR;
        SET @step = @step + 1;
END   
CLOSE MYTESTCURSOR
DEALLOCATE MYTESTCURSOR

1

MSはt-sqlのLIMITをサポートしていません。ほとんどの場合、MAX(ID)を取得してから減算します。

select * from ORDERS where ID >(select MAX(ID)-10 from ORDERS)

IDがシーケンシャルでない場合、これは10レコード未満を返します。


0

非常に大きなテーブル(1億以上100万または10億以上の行)MOST RECENT行をクエリするために使用する手法では、最新の "N"パーセントのRECENT ROWSのみを "読み取り"にクエリを制限しています。これは実際のアプリケーションです。たとえば、非履歴の最近の気象データ、最近のニュースフィード検索、最近のGPS位置データポイントデータに対してこれを行います。

たとえば、行がテーブルの最新のTOP 5%にあることが確実にわかっている場合、これはパフォーマンスが大幅に向上します。そのため、テーブルにインデックスがある場合でも、1億を超える行または10億を超える行を含むテーブルの行の5%のみに制限される可能性があります。これは特に、古いデータが論理メモリ内読み取りだけでなく物理ディスク読み取りを必要とする場合に当てはまります。

これはSELECT TOPよりもはるかに効率的です。PERCENT | LIMITは行を選択しないため、検索するデータの部分を制限するだけです。

DECLARE @RowIdTableA BIGINT
DECLARE @RowIdTableB BIGINT
DECLARE @TopPercent FLOAT

-- Given that there is an Sequential Identity Column
-- Limit query to only rows in the most recent TOP 5% of rows
SET @TopPercent = .05
SELECT @RowIdTableA = (MAX(TableAId) - (MAX(TableAId) * @TopPercent)) FROM TableA
SELECT @RowIdTableB = (MAX(TableBId) - (MAX(TableBId) * @TopPercent)) FROM TableB

SELECT *
FROM TableA a
INNER JOIN TableB b ON a.KeyId = b.KeyId
WHERE a.Id > @RowIdTableA AND b.Id > @RowIdTableB AND
      a.SomeOtherCriteria = 'Whatever'

-1

を使用せずに最後の3行を表示するにはorder by

select * from Lms_Books_Details where Book_Code not in 
 (select top((select COUNT(*) from Lms_Books_Details ) -3 ) book_code from Lms_Books_Details) 

1
これは予測可能な結果を​​提供しません。SQL ServerのMSDNドキュメント(msdn.microsoft.com/en-us/library/ms189463.aspx)によると: "TOPがORDER BY句と組み合わせて使用​​される場合、結果セットは順序付けられた最初のN個に制限されます行、それ以外の場合は、未定義の順序で最初のN個の行を返します。
caveman_dick

-1

EXCEPT構文を使用してみてください。
このようなもの:

   SELECT * 
    FROM   clientDetails 
    EXCEPT 
    (SELECT TOP (numbers of rows - how many rows you want) * 
     FROM   clientDetails) 

@Prafulla Sutradharと同じ回答
DMK

-1

少し遅いかもしれませんが、ここにあなたの質問を解決する簡単な選択があります。

SELECT * FROM "TABLE" T ORDER BY "T.ID_TABLE" DESC LIMIT 5;
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.