Câu trả lời:
SELECT
columns
FROM
(
SELECT TOP 200
columns
FROM
My_Table
ORDER BY
a_column DESC
) SQ
ORDER BY
a_column ASC
Nó là không cần thiết. Bạn có thể sử dụng một ORDER BY
và chỉ cần thay đổi cách sắp xếp DESC
để có được hiệu quả tương tự.
Xin lỗi, nhưng tôi không nghĩ rằng tôi thấy bất kỳ câu trả lời chính xác nào theo quan điểm của tôi.
Hàm TOP
x hiển thị các bản ghi theo thứ tự không xác định. Từ định nghĩa đó dẫn đến một BOTTOM
hàm không thể được định nghĩa.
Không phụ thuộc vào bất kỳ chỉ mục hoặc thứ tự sắp xếp nào. Khi bạn thực hiện, ORDER BY y DESC
bạn sẽ nhận được các hàng có giá trị y cao nhất trước tiên. Nếu đây là ID được tạo tự động, nó sẽ hiển thị các bản ghi được thêm lần cuối vào bảng, như được đề xuất trong các câu trả lời khác. Tuy nhiên:
TOP
hàmCâu trả lời đúng phải là không, và không thể, tương đương với TOP
để lấy các hàng dưới cùng.
Một cách hợp lý,
BOTTOM (x) is all the records except TOP (n - x), where n is the count; x <= n
Ví dụ: Chọn dưới cùng 1000 từ Nhân viên:
Trong T-SQL,
DECLARE
@bottom int,
@count int
SET @bottom = 1000
SET @count = (select COUNT(*) from Employee)
select * from Employee emp where emp.EmployeeID not in
(
SELECT TOP (@count-@bottom) Employee.EmployeeID FROM Employee
)
Có vẻ như bất kỳ câu trả lời nào triển khai mệnh đề ORDER BY trong giải pháp đều bị thiếu điểm hoặc không thực sự hiểu TOP trả về cho bạn những gì.
TOP trả về tập kết quả truy vấn không có thứ tự giới hạn tập hợp bản ghi ở N bản ghi đầu tiên được trả về. (Theo quan điểm của Oracle, nó giống với việc thêm một where ROWNUM <(N + 1).
Bất kỳ giải pháp nào sử dụng thứ tự, đều có thể trả về các hàng cũng được trả về bởi mệnh đề TOP (vì tập dữ liệu đó không có thứ tự ở vị trí đầu tiên), tùy thuộc vào tiêu chí nào được sử dụng trong thứ tự
Tính hữu ích của TOP là khi tập dữ liệu đạt đến kích thước N nhất định, nó sẽ ngừng tìm nạp các hàng. Bạn có thể cảm nhận dữ liệu trông như thế nào mà không cần phải tìm nạp tất cả.
Để triển khai BOTTOM một cách chính xác, nó sẽ cần tìm nạp toàn bộ tập dữ liệu không có thứ tự và sau đó hạn chế tập dữ liệu ở N bản ghi cuối cùng. Điều đó sẽ không đặc biệt hiệu quả nếu bạn đang xử lý các bảng lớn. Nó cũng không nhất thiết phải cung cấp cho bạn những gì bạn nghĩ bạn đang yêu cầu. Phần cuối của tập dữ liệu có thể không nhất thiết phải là "các hàng cuối cùng được chèn" (và có thể sẽ không dành cho hầu hết các ứng dụng chuyên sâu DML).
Tương tự như vậy, các giải pháp triển khai ORDER BY, thật không may, có khả năng gây tai hại khi xử lý các tập dữ liệu lớn. Chẳng hạn, nếu tôi có 10 Tỷ bản ghi và muốn có 10 bản cuối cùng, thì thật là ngu ngốc khi đặt hàng 10 Tỷ bản ghi và chọn 10 bản cuối cùng.
Vấn đề ở đây là ĐÁY không có ý nghĩa mà chúng ta nghĩ đến khi so sánh nó với TOP.
Khi các bản ghi được chèn, xóa, chèn, xóa nhiều lần, một số khoảng trống sẽ xuất hiện trong bộ nhớ và sau đó, các hàng sẽ được sắp xếp vào, nếu có thể. Nhưng những gì chúng ta thường thấy, khi chúng ta chọn TOP, dường như là dữ liệu đã được sắp xếp, bởi vì nó có thể đã được chèn từ rất sớm trong sự tồn tại của bảng. Nếu bảng không bị xóa nhiều lần, bảng có thể xuất hiện để được đặt hàng. (ví dụ: ngày tạo có thể xa hơn thời gian so với ngày tạo bảng). Nhưng thực tế là, nếu đây là một bảng nặng về tính năng xóa, thì các hàng TOP N có thể không giống như vậy chút nào.
Vì vậy, điểm mấu chốt ở đây (ý định chơi chữ) là một người nào đó đang yêu cầu các bản ghi BOTTOM N thực sự không biết họ đang yêu cầu điều gì. Hoặc, ít nhất, những gì họ yêu cầu và những gì BOTTOM thực sự có nghĩa là không giống nhau.
Vì vậy - giải pháp có thể đáp ứng nhu cầu kinh doanh thực tế của người yêu cầu ... nhưng không đáp ứng tiêu chí trở thành ĐÁY.
insert
câu lệnh lớn để đặt các hàng vào một bảng lớn, không được lập chỉ mục. (Tôi đang điền bảng trước khi bắt đầu lập chỉ mục.) Tôi đã mất phiên khách hàng của mình do khởi động lại hoặc bất cứ điều gì, và bây giờ tôi muốn xem liệu các hàng mới được thêm của tôi có ở đó hay không. Nếu hàng 'dưới cùng' của bảng là một trong những hàng gần đây của tôi, tôi biết thao tác đã hoàn tất. Nếu hàng 'dưới cùng' là thứ khác, thì không có gì đảm bảo và tôi phải quét toàn bộ bảng để chắc chắn ... nhưng rất có thể tôi có thể tiết kiệm thời gian bằng cách nhanh chóng kiểm tra 'dưới cùng' giống như bạn có thể ' hàng đầu'.
Câu trả lời hiện được chấp nhận bởi "Justin Ethier" không phải là một câu trả lời chính xác như được chỉ ra bởi "Protector one".
Theo như tôi thấy, cho đến thời điểm hiện tại, không có câu trả lời hoặc nhận xét nào khác tương đương với BOTTOM (x) mà tác giả câu hỏi yêu cầu.
Trước tiên, hãy xem xét một tình huống mà chức năng này sẽ cần thiết:
SELECT * FROM Split('apple,orange,banana,apple,lime',',')
Điều này trả về một bảng gồm một cột và năm bản ghi:
Như bạn có thể thấy: chúng tôi không có cột ID; chúng tôi không thể đặt hàng theo cột trả về; và chúng ta không thể chọn hai bản ghi dưới cùng bằng cách sử dụng SQL tiêu chuẩn như chúng ta có thể làm cho hai bản ghi trên cùng.
Đây là nỗ lực của tôi để cung cấp giải pháp:
SELECT * INTO #mytemptable FROM Split('apple,orange,banana,apple,lime',',')
ALTER TABLE #mytemptable ADD tempID INT IDENTITY
SELECT TOP 2 * FROM #mytemptable ORDER BY tempID DESC
DROP TABLE #mytemptable
Và đây là một giải pháp hoàn chỉnh hơn:
SELECT * INTO #mytemptable FROM Split('apple,orange,banana,apple,lime',',')
ALTER TABLE #mytemptable ADD tempID INT IDENTITY
DELETE FROM #mytemptable WHERE tempID <= ((SELECT COUNT(*) FROM #mytemptable) - 2)
ALTER TABLE #mytemptable DROP COLUMN tempID
SELECT * FROM #mytemptable
DROP TABLE #mytemptable
Tôi hoàn toàn không khẳng định rằng đây là một ý tưởng hay để sử dụng trong mọi trường hợp, nhưng nó mang lại kết quả mong muốn.
Tất cả những gì bạn cần làm là đảo ngược của bạn ORDER BY
. Thêm hoặc xóa DESC
nó.
Vấn đề với việc đặt hàng theo cách khác là nó thường không tận dụng tốt các chỉ số. Nó cũng không thể mở rộng nhiều nếu bạn cần chọn một số hàng không ở đầu hoặc cuối. Một cách thay thế như sau.
DECLARE @NumberOfRows int;
SET @NumberOfRows = (SELECT COUNT(*) FROM TheTable);
SELECT col1, col2,...
FROM (
SELECT col1, col2,..., ROW_NUMBER() OVER (ORDER BY col1) AS intRow
FROM TheTable
) AS T
WHERE intRow > @NumberOfRows - 20;
Câu trả lời "Tom H" ở trên là đúng và nó phù hợp với tôi khi nhận được 5 hàng Dưới cùng.
SELECT [KeyCol1], [KeyCol2], [Col3]
FROM
(SELECT TOP 5 [KeyCol1],
[KeyCol2],
[Col3]
FROM [dbo].[table_name]
ORDER BY [KeyCol1],[KeyCol2] DESC) SOME_ALAIS
ORDER BY [KeyCol1],[KeyCol2] ASC
Cảm ơn.
thử cái này.
declare @floor int --this is the offset from the bottom, the number of results to exclude
declare @resultLimit int --the number of results actually retrieved for use
declare @total int --just adds them up, the total number of results fetched initially
--following is for gathering top 60 results total, then getting rid of top 50. We only keep the last 10
set @floor = 50
set @resultLimit = 10
set @total = @floor + @resultLimit
declare @tmp0 table(
--table body
)
declare @tmp1 table(
--table body
)
--this line will drop the wanted results from whatever table we're selecting from
insert into @tmp0
select Top @total --what to select (the where, from, etc)
--using floor, insert the part we don't want into the second tmp table
insert into @tmp1
select top @floor * from @tmp0
--using select except, exclude top x results from the query
select * from @tmp0
except
select * from @tmp1
Tôi đã đưa ra một giải pháp cho điều này mà không yêu cầu bạn biết số hàng được trả về.
Ví dụ: nếu bạn muốn ghi tất cả các vị trí vào một bảng, ngoại trừ vị trí 1 (hoặc 2, hoặc 5, hoặc 34) mới nhất
SELECT *
FROM
(SELECT ROW_NUMBER() OVER (ORDER BY CreatedDate) AS Row, *
FROM Locations
WHERE UserId = 12345) AS SubQuery
WHERE Row > 1 -- or 2, or 5, or 34
Truy vấn một truy vấn con đơn giản được sắp xếp giảm dần, tiếp theo là sắp xếp trên cùng một cột tăng dần là mẹo nhỏ.
SELECT * FROM
(SELECT TOP 200 * FROM [table] t2 ORDER BY t2.[column] DESC) t1
ORDER BY t1.[column]
SELECT TOP 10*from TABLE1 ORDER BY ID DESC
Trong đó ID là khóa chính của TABLE1.
Đầu tiên, hãy tạo một chỉ mục trong một truy vấn con theo thứ tự ban đầu của bảng bằng cách sử dụng:
ROW_NUMBER () OVER (ORDER BY (SELECT NULL) ) AS RowIndex
Sau đó, sắp xếp bảng giảm dần theo RowIndex
cột bạn đã tạo trong truy vấn chính:
ORDER BY RowIndex DESC
Và cuối cùng sử dụng TOP
với số lượng hàng mong muốn của bạn:
SELECT TOP 1 * --(or 2, or 5, or 34)
FROM (SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL) ) AS RowIndex, *
FROM MyTable) AS SubQuery
ORDER BY RowIndex DESC