web-dev-qa-db-ja.com

SQL ServerのSELECT LAST N ROW

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

SELECT TOP N *
FROM MyTable
ORDER BY Id DESC

たくさんの行があるテーブルです。時間がかかるため、このクエリを使用することは不可能です。では、どうすればORDER BYを使わずに最後のN行を選択することができるのでしょうか。

編集

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

119
Diego

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

NorthwindデータベースのOrdersテーブルを使用しています...今度は、Employee 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
34
JonVD

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

select * from tbl_name order by id desc limit N;
82

私はJonVDのコードをテストしましたが、とても遅い6秒だとわかりました。

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

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

テーブルから最後の行数を選択したい場合。

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

 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)
15

"Id"はインデックスされていますか?そうでなければ、それはするべき重要なことです(私はそれが既に索引付けされていると思う)。

また、すべての列を返す必要がありますか?あなたが実際にIDカラムのインデックスによって完全に対応することができるカラムのより小さなサブセットを必要とするなら、あなたはスピードのかなりの改善を得ることができるかもしれません - 例えば。 Id列にNONCLUSTERED索引があり、他のフィールドが索引に含まれていない場合は、残りの列を実際に返すためにクラスター化索引をルックアップする必要があります。クエリのコストそれがCLUSTEREDインデックス、またはあなたがクエリで返したい他のすべてのフィールドを含むNONCLUSTEREDインデックスであるならば、あなたは問題ないはずです。

6
AdaTheDev

非常に一般的な方法で、そしてここでSQLサーバーをサポートすることは、

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

そして性能のために、それは悪くないです(サーバーマシンの10,000以上の記録のための1秒以下)

6
Hakam Fostok

まず、あなたはほとんどからレコード数を得ます

 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 
5
select * from (select top 6 * from vwTable order by Hours desc) T order by Hours
4
fth

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

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

前述のように、どの行が返されるかは未定義です。

編集:これは実際に犬遅いです。本当に価値がないです。

4
Dzamo Norton

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

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

最後の値を取得するには、クエリの末尾でdescとorderbyを使用します。

2
Sara

これは質問に完全には適さないかもしれませんが…

OFFSET句

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

そのdocリンクはPostgresへのものです。これがSybase/MS SQL Serverに当てはまるかどうかわかりません。

1
Basil Bourque

非常に大きなテーブル内の MOST RECENT 行を照会するために使用する技法(1億以上または10億以上の行)は、最新の「N」パーセントの「最近の行」のみを照会の「読み取り」に制限しています。これは現実世界のアプリケーションです。例えば、私は歴史的でない最近の天気データ、最近のニュースフィード検索、最近のGPS位置データポイントデータに対してこれを行います。

たとえば、行がテーブルの最新の上位5%にあることが確実であれば、これは大幅なパフォーマンスの向上になります。テーブルにインデックスがある場合でも、1億以上または10億以上の行を持つテーブル内の行の5%に可能性が限定されます。これは、古いデータが物理ディスク readを必要とし、 Logical In Memory readだけではない場合に特に当てはまります。

これは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'
0
CodeCowboyOrg
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
0
Slava