Відповіді:
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
ви отримуєте рядки з найвищим значенням у. Якщо це автогенерований ідентифікатор, він повинен відображати записи, які останнім часом були додані до таблиці, як це запропоновано в інших відповідях. Однак:
TOP
функцієюПравильна відповідь повинна полягати в тому, що немає та не може бути еквівалентом TOP
для отримання нижніх рядків.
Логічно,
BOTTOM (x) is all the records except TOP (n - x), where n is the count; x <= n
Напр. Вибір дна 1000 від працівника:
У 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
)
Здавалося б, у будь-якому з відповідей, які реалізують пункт 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, насправді не знає, про що вони просять. Або, принаймні, те, що вони просять і що BOTTOM насправді означає, - це не те саме.
Отже - рішення може задовольнити фактичну ділову потребу запитувача ..., але не відповідає критеріям БУТЬ.
insert
заяву, щоб помістити рядки у велику, недекларовану таблицю. (Я заповнюю таблицю спочатку, перш ніж почати її індексувати.) Я втратив сеанс свого клієнта через перезавантаження чи будь-що інше, і тепер я хочу перевірити, чи є у мене щойно додані рядки. Якщо "нижній" рядок таблиці є одним із моїх останніх, я знаю, що операція завершена. Якщо "нижній" рядок є чимось іншим, ну ніяких гарантій немає, і мені доведеться сканувати всю таблицю, щоб переконатися ... але, швидше за все, я міг би заощадити час, швидко перевіривши "дно" так само, як ви можете " верх '.
На даний момент прийнята відповідь "Джастіна Етьє" не є правильною відповіддю, на що вказував "Протектор один".
Наскільки я бачу, на даний момент жодна інша відповідь чи коментар не забезпечує еквівалент BOTTOM (x) на запитання автора, який запитував.
Спочатку розглянемо сценарій, коли ця функціональність буде потрібна:
SELECT * FROM Split('apple,orange,banana,apple,lime',',')
Це повертає таблицю з одного стовпця та п'яти записів:
Як бачите: у нас немає стовпця з ідентифікатором; ми не можемо замовити повернутий стовпець; і ми не можемо вибрати два найнижчих записи, використовуючи стандартний 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
Я ні в якому разі не стверджую, що цю ідею слід використовувати в будь-яких обставинах, але вона дає бажані результати.
Все, що вам потрібно зробити, це відмінити ваше ORDER BY
. Додайте або видаліть DESC
до нього.
Проблема із замовленням іншого способу полягає в тому, що він часто не використовує індекси. Це також не дуже розширюється, якщо вам коли-небудь потрібно вибрати ряд рядків, які не знаходяться на початку чи в кінці. Альтернативний спосіб полягає в наступному.
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;
Відповідь "Том Н" вище є правильною, і це працює для мене в отриманні нижнього 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
Дякую.
спробуйте це.
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 TOP 10*from TABLE1 ORDER BY ID DESC
Де ID є первинним ключем ТАБЛИЦІ1.
Спочатку створіть індекс у підзапиті відповідно до початкового порядку таблиці, використовуючи:
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