Как выбрать самые нижние строки?

Я могу выбрать TOP (200) ... но почему не снизу (200)?

ну, чтобы не попасть в философию, что я имею в виду, как я могу сделать эквивалент TOP (200), но наоборот (снизу, как вы ожидаете, снизу...)?

13 ответов


SELECT
    columns
FROM
(
     SELECT TOP 200
          columns
     FROM
          My_Table
     ORDER BY
          a_column DESC
) SQ
ORDER BY
     a_column ASC

это лишнее. Вы можете использовать ORDER BY и просто изменить вид DESC чтобы получить тот же эффект.


Извините, но я не думаю, что я вижу правильные ответы на мой взгляд.

на TOP функция x показывает записи в неопределенном порядке. Из этого определения следует, что BOTTOM функция не может быть определена.

независимо от любого индекса или порядка сортировки. Когда вы делаете ORDER BY y DESC сначала вы получаете строки с самым высоким значением Y. Если это АВТОГЕНЕРИРОВАННЫЙ идентификатор, он должен показывать записи, последние добавленные в таблицу, как предложено в других ответах. Однако:

  • это работает только в том случае, если есть столбец autogenerated id
  • это оказывает значительное влияние на производительность, если вы сравните это с TOP функции

правильным ответом должно быть то, что нет и не может быть эквивалента TOP для получения нижних рядов.


выберите Нижний 1000 из Employee

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
)

все, что вам нужно сделать, это изменить свое ORDER BY. Добавить или удалить DESC к нему.


В настоящее время принятый ответ "Justin Ethier" не является правильным ответом, как указано "Protector one".

насколько я вижу, на данный момент ни один другой ответ или комментарий не дает эквивалента нижней(x) вопрос, заданный автором.

во-первых, давайте рассмотрим сценарий, где эта функциональность будет необходима:

SELECT * FROM Split('apple,orange,banana,apple,lime',',')

Это возвращает таблицу из одного столбца и пять записи:

  • яблоко
  • оранжевый
  • банан
  • яблоко
  • извести

как вы можете видеть: у нас нет столбца ID; мы не можем заказать по возвращаемому столбцу; и мы не можем выбрать нижние две записи, используя стандартный SQL, как мы можем сделать для двух верхних записей.

вот моя попытка предложить решение:

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

и вот более полный решение:

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

проблема с заказом другим способом заключается в том, что он часто не использует индексы. Он также не очень расширяется, если вам нужно выбрать несколько строк, которые не находятся в начале или конце. Альтернативный способ заключается в следующем.

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;

" Tom H " ответ выше правильный, и он работает для меня в получении нижних 5 строк.

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

спасибо.


казалось бы, что любой из ответов, которые реализуют предложение ORDER BY в решении, отсутствует или фактически не понимает, что TOP возвращает вам.

TOP возвращает неупорядоченный результирующий набор запроса, который ограничивает набор записей первыми n возвращенными записями. (С точки зрения Oracle, это сродни добавлению where ROWNUM

любое решение, которое использует ордера мая возвращаемые строки, которые также возвращаются предложением TOP (поскольку этот набор данных был неупорядоченным в первую очередь), в зависимости от того, какие критерии использовались в порядке

полезность TOP заключается в том, что как только набор данных достигает определенного размера N, он перестает извлекать строки. Вы можете почувствовать, как выглядят данные, без необходимости извлекать их все.

чтобы реализовать BOTTOM точно, ему нужно будет получить весь неупорядоченный набор данных, а затем ограничить набор данных конечными N записями. Это будет не особенно эффективным, если вы имеете дело с огромными таблицами. И это не обязательно даст вам то, что вы думаю вы просите. Конец набора данных может не обязательно быть "последними вставленными строками" (и, вероятно, не будет для большинства интенсивных приложений DML).

аналогично, решения, которые реализуют заказ, к сожалению, потенциально катастрофичны при работе с большими наборами данных. Если у меня есть, скажем, 10 миллиардов записей и я хочу последние 10, довольно глупо заказывать 10 миллиардов записей и выберите последние 10.

проблема здесь в том, что дно не имеет значения, что мы думать при сравнении его с TOP.

когда записи вставляются, удаляются, вставляются, удаляются снова и снова, в хранилище появятся некоторые пробелы, а позже строки будут вставлены, если это возможно. Но то, что мы часто видим, когда выбираем TOP,появляется для сортировки данных, потому что он может быть вставлен в начале существование стола. Если таблица не испытывает много удалений, она может появляется, котор нужно приказать. (например, даты создания могут быть такими же далекими во времени, как и само создание таблицы). Но реальность такова, что если это таблица delete-heavy, верхние N строк могут выглядеть совсем не так.

Итак, суть здесь (каламбур) заключается в том, что кто-то, кто просит нижние N записей, на самом деле не знает, о чем они просят. Или, по крайней мере, то, о чем они просят. то, что на самом деле означает "дно", не одно и то же.

Так-решение может удовлетворить бизнес-потребности заказчика...но не удовлетворяет критериям быть нижним.


SELECT TOP 10*from TABLE1 ORDER BY ID DESC

где ID является первичным ключом таблицы.


попробуйте это.

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

Я придумал решение, которое не требует, чтобы вы знали число строк, возвращаемых.

например, если вы хотите получить все местоположения, зарегистрированные в таблице, за исключением последнего 1 (или 2, или 5, или 34)

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

запрос простого подзапроса, отсортированного по убыванию, с последующей сортировкой по тому же столбцу по возрастанию, делает трюк.

SELECT * FROM 
    (SELECT TOP 200 * FROM [table] t2 ORDER BY t2.[column] DESC) t1
    ORDER BY t1.[column]