Я могу сделать SELECT TOP (200)... но почему бы не BOTTOM (200)?
Ну, чтобы не вникать в философию, что я имею в виду, как я могу сделать эквивалент TOP (200), но наоборот (снизу, как вы ожидали бы BOTTOM...)?
Я могу сделать SELECT TOP (200)... но почему бы не BOTTOM (200)?
Ну, чтобы не вникать в философию, что я имею в виду, как я могу сделать эквивалент TOP (200), но наоборот (снизу, как вы ожидали бы BOTTOM...)?
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 показывает записи в порядке undefined. Из этого определения следует, что a BOTTOM
не может быть определена.
Независимо от любого индекса или порядка сортировки. Когда вы выполняете ORDER BY y DESC
, сначала получаете строки с наивысшим значением y. Если это автогенерированный идентификатор, он должен показывать записи, добавленные последним в таблицу, как это было предложено в других ответах. Однако:
TOP
Правильный ответ должен состоять в том, что для получения нижних строк нет и не может быть эквивалентом TOP
.
Выберите "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
)
Все, что вам нужно сделать, это отменить ваш ORDER BY
. Добавьте или удалите DESC
.
Нынешний принятый ответ "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
Я никоим образом не утверждаю, что это хорошая идея для использования во всех обстоятельствах, но она дает желаемые результаты.
Проблема с упорядочением по-другому заключается в том, что она часто не использует индексы. Он также не очень расширяем, если вам нужно выбрать несколько строк, которые не находятся в начале или в конце. Альтернативный способ заключается в следующем.
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;
Ответ "Том Н" выше, это правильно, и он работает для меня в получении строк "Нижний".
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 это похоже на добавление куда ROWNUM <(N + 1).
Любое решение, использующее порядок, может возвращать строки, которые также возвращаются предложением TOP (поскольку этот набор данных был неупорядоченным в первую очередь), в зависимости от того, какие критерии использовались в порядке
Полезность TOP состоит в том, что как только набор данных достигает определенного размера N, он прекращает выборку строк. Вы можете почувствовать, как выглядят данные без необходимости извлекать их все.
Для точной реализации BOTTOM потребуется получить весь неупорядоченный набор данных, а затем ограничить набор данных окончательными N записями. Это не будет особенно эффективно, если вы имеете дело с огромными столами. И при этом это не обязательно даст вам то, о чем вы думаете. Конец набора данных не обязательно должен быть "последними вставленными строками" (и, вероятно, не будет для большинства приложений, интенсивно использующих DML).
Аналогичным образом, решения, которые реализуют ORDER BY, к сожалению, потенциально катастрофичны при работе с большими наборами данных. Если у меня есть, скажем, 10 миллиардов записей и я хочу последние 10, то глупо заказывать 10 миллиардов записей и выбирать последние 10.
Проблема здесь в том, что BOTTOM не имеет значения, о котором мы думаем, сравнивая его с TOP.
Когда записи вставляются, удаляются, вставляются, удаляются снова и снова и снова, в хранилище будут появляться некоторые пробелы, и позже строки будут вставлены в интервалы, если это возможно. Но то, что мы часто видим, когда выбираем TOP, похоже, отсортированные данные, потому что они могли быть вставлены в самом начале существования таблицы. Если таблица не имеет большого количества удалений, она может показаться упорядоченной. (Например, даты создания могут быть так же давно, как и само создание таблицы). Но реальность такова, что если это таблица с интенсивным удалением, строки TOP N могут выглядеть совсем не так.
Итак, суть здесь (каламбур) заключается в том, что тот, кто запрашивает записи BOTTOM N, на самом деле не знает, о чем они просят. Или, по крайней мере, то, что они просят, и что фактически означает ДНО, - это не одно и то же.
Таким образом, решение может соответствовать фактическим бизнес-потребностям запрашивающей стороны, но не соответствует критериям для ДНА.
SELECT TOP 10*from TABLE1 ORDER BY ID DESC
Где ID - это первичный ключ TABLE1.
попробуйте это.
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]
Сначала создайте индекс в подзапросе в соответствии с исходным порядком таблицы, используя:
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