Как выбрать нижнюю часть строк?

Я могу сделать SELECT TOP (200)... но почему бы не BOTTOM (200)?

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

Ответ 1

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

Ответ 2

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

Ответ 3

Извините, но, по-моему, я не вижу правильных ответов.

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

Независимо от любого индекса или порядка сортировки. Когда вы выполняете ORDER BY y DESC, сначала получаете строки с наивысшим значением y. Если это автогенерированный идентификатор, он должен показывать записи, добавленные последним в таблицу, как это было предложено в других ответах. Однако:

  • Это работает только в том случае, если имеется столбец с автогенерированным идентификатором
  • Он имеет значительное влияние на производительность, если сравнить его с функцией TOP

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

Ответ 4

Выберите "Bottom 1000 from 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 (@[email protected]) Employee.EmployeeID FROM Employee
)

Ответ 5

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

Ответ 6

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

Насколько я вижу, на данный момент никакой другой ответ или комментарий не дает эквивалент BOTTOM (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

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

Ответ 7

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

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;

Ответ 8

Ответ "Том Н" выше, это правильно, и он работает для меня в получении строк "Нижний".

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

Спасибо.

Ответ 9

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

TOP возвращает неупорядоченный набор результатов запроса, который ограничивает набор записей первыми N возвращенными записями. (С точки зрения Oracle это похоже на добавление куда ROWNUM <(N + 1).

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

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

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

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

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

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

Итак, суть здесь (каламбур) заключается в том, что тот, кто запрашивает записи BOTTOM N, на самом деле не знает, о чем они просят. Или, по крайней мере, то, что они просят, и что фактически означает ДНО, - это не одно и то же.

Таким образом, решение может соответствовать фактическим бизнес-потребностям запрашивающей стороны, но не соответствует критериям для ДНА.

Ответ 10

SELECT TOP 10*from TABLE1 ORDER BY ID DESC

Где ID - это первичный ключ TABLE1.

Ответ 11

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

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

Ответ 12

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

Например, если вы хотите, чтобы все локации регистрировались в таблице, за исключением последних 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

Ответ 13

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

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

Ответ 14

Сначала создайте индекс в подзапросе в соответствии с исходным порядком таблицы, используя:

ROW_NUMBER () OVER (ORDER BY (SELECT NULL) ) AS RowIndex

Затем упорядочите таблицу по убыванию по столбцу RowIndex вы создали в основном запросе:

ORDER BY RowIndex DESC

И, наконец, используйте TOP с требуемым количеством строк:

    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