답변:
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 값을 가진 행을 먼저 얻습니다. 이것이 자동 생성 된 ID 인 경우 다른 답변에서 제안 된대로 테이블에 마지막으로 추가 된 레코드를 표시해야합니다. 하나:
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 개 레코드로 제한하는 정렬되지 않은 쿼리 결과 집합을 반환합니다. (오라클 관점에서는 where ROWNUM <(N + 1)을 추가하는 것과 유사합니다.
순서를 사용하는 모든 솔루션 은 순서에 사용 된 기준에 따라 TOP 절에 의해 반환되는 행을 반환 할 수 있습니다 (데이터 집합이 처음에 순서가 지정되지 않았기 때문에).
TOP의 유용성은 데이터 세트가 특정 크기 N에 도달하면 행 가져 오기를 중지한다는 것입니다. 데이터를 모두 가져 오지 않고도 데이터가 어떻게 보이는지 느낄 수 있습니다.
BOTTOM을 정확하게 구현하려면 순서가 지정되지 않은 전체 데이터 세트를 가져온 다음 데이터 세트를 최종 N 개 레코드로 제한해야합니다. 거대한 테이블을 다루는 경우에는 특히 효과적이지 않습니다. 그것은 당신이 생각 하는 것을 반드시 당신에게주지 않을 것입니다 당신이 요구하고 입니다. 데이터 세트의 끝이 반드시 "마지막으로 삽입 된 행"일 필요는 없습니다 (그리고 대부분의 DML 집약적 애플리케이션에는 해당되지 않을 것입니다).
마찬가지로, ORDER BY를 구현하는 솔루션은 안타깝게도 대규모 데이터 세트를 처리 할 때 잠재적으로 재앙이 될 수 있습니다. 예를 들어 100 억 개의 레코드가 있고 마지막 10 개를 원한다면 100 억 개의 레코드를 주문하고 마지막 10 개를 선택하는 것은 어리석은 일입니다.
여기서 문제는 BOTTOM이 TOP과 비교할 때 생각 하는 의미가 없다는 것입니다 .
레코드가 삽입, 삭제, 삽입, 삭제 될 때 저장소에 약간의 간격이 나타나고 나중에 가능하면 행이 슬롯에 들어갑니다. 그러나 TOP을 선택 하면 테이블의 존재 초기에 삽입되었을 수 있으므로 정렬 된 데이터 인 것처럼 보입니다 . 테이블이 많이 삭제되지 않으면 나타날 수 있습니다. 정렬 된 수 있습니다. (예를 들어, 생성 날짜는 테이블 생성 자체만큼 과거의 시간 일 수 있습니다). 그러나 현실은 이것이 삭제가 많은 테이블 인 경우 TOP N 행이 전혀 그렇게 보이지 않을 수 있다는 것입니다.
그래서-여기서 결론은 (말장난 의도) BOTTOM N 레코드를 요청하는 사람이 실제로 요청하는 내용을 알지 못한다는 것입니다. 또는 적어도 그들이 요구하는 것과 BOTTOM이 실제로 의미하는 바는 같은 것이 아닙니다.
따라서 솔루션은 요청자의 실제 비즈니스 요구를 충족시킬 수 있지만 BOTTOM이되는 기준을 충족하지 않습니다.
insert
문을 실행하여 색인화되지 않은 큰 테이블에 행을 넣었습니다. (인덱싱을 시작하기 전에 먼저 테이블을 채우고 있습니다.) 재부팅 등으로 인해 클라이언트 세션이 손실되었습니다. 이제 새로 추가 된 행이 거기에 있는지 확인하고 싶습니다. 테이블의 '맨 아래'행이 최근 행 중 하나라면 작업이 완료된 것입니다. '하단'행이 다른 경우에는 보장 할 수 없으며 확인하기 위해 전체 테이블을 스캔해야합니다 ...하지만 '하단'을 빠르게 확인하여 시간을 절약 할 수 있습니다. 상단'.
현재 "Justin Ethier"가 받아 들인 답변은 "Protector One"이 지적한 정답이 아닙니다.
내가 볼 수있는 한, 현재로서는 작성자가 요청한 BOTTOM (x)에 해당하는 다른 답변이나 의견이 없습니다.
먼저이 기능이 필요한 시나리오를 고려해 보겠습니다.
SELECT * FROM Split('apple,orange,banana,apple,lime',',')
그러면 열 1 개와 레코드 5 개로 구성된 테이블이 반환됩니다.
보시다시피 : ID 열이 없습니다. 반환 된 열로 주문할 수 없습니다. 상위 2 개 레코드에 대해 할 수있는 것처럼 표준 SQL을 사용하여 하위 2 개 레코드를 선택할 수 없습니다.
해결책을 제공하려는 시도는 다음과 같습니다.
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
감사.
이 시도.
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
SELECT TOP 10*from TABLE1 ORDER BY ID DESC
여기서 ID는 TABLE1의 기본 키입니다.
먼저 다음을 사용하여 테이블의 원래 순서에 따라 하위 쿼리에 인덱스를 만듭니다.
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