programing

맨 아래 행을 선택하는 방법

topblog 2023. 4. 23. 09:57
반응형

맨 아래 행을 선택하는 방법

SELECT TOP (200)은 할 수 있는데 왜 BOOTHOW (200)는 할 수 없는 거죠?

철학적으로 설명하지 말고 어떻게 TOP(200)와 동등하지만 반대로(아래에서 BOOTOM이 기대하는 것처럼...) 할 수 있을까요?

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는 y값이 가장 높은 행이 나옵니다.이것이 자동 생성된 ID인 경우, 다른 답변에서 제시된 것처럼 테이블에 마지막으로 추가된 레코드가 표시됩니다. : ,,

  • 이것은 자동 생성된 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개의 레코드로 레코드 세트를 제한하는 순서 없는 쿼리 결과 세트를 반환합니다(Oracle 관점에서 이는 ROWNUM < (N+1)을 추가하는 것과 유사합니다).

순서를 사용하는 솔루션은 TOP 절에 의해 반환되는 행을 반환할 수 있습니다(처음에는 데이터 세트가 순서가 지정되지 않았기 때문에).

TOP의 유용성은 데이터 집합이 특정 크기 N에 도달하면 행 가져오기를 중지한다는 것입니다.데이터를 모두 가져올 필요 없이 데이터가 어떻게 표시되는지 알 수 있습니다.

BOTOM을 정확하게 구현하려면 전체 데이터 집합을 순서 없이 가져온 다음 데이터 집합을 최종 N개 레코드로 제한해야 합니다.큰 테이블을 취급하고 있는 경우는 그다지 효과적이지 않습니다.또한 당신이 원하는 것을 반드시 얻을 수 있는 것도 아닙니다.데이터 세트의 끝부분이 반드시 "마지막으로 삽입된 행"은 아닐 수 있습니다(대부분의 DML 부하가 높은 애플리케이션에서는 그렇지 않을 수도 있습니다).

마찬가지로 ORDER BY를 구현하는 솔루션은 불행히도 대규모 데이터 세트를 처리할 때 치명적일 수 있습니다.예를 들어 내가 100억 개의 레코드를 가지고 있고 마지막 100억 개의 레코드를 원한다면, 100억 개의 레코드를 주문하고 마지막 10개를 선택하는 것은 매우 어리석은 일이다.

여기서 문제는 TOP과 비교할 때 우리가 생각하는 BOTOM의 의미가 없다는 것입니다.

레코드가 삽입, 삭제, 삽입, 삭제가 반복되면 스토리지에 공백이 생기고 나중에 가능하면 행이 슬롯에 배치됩니다.그러나 TOP를 선택하면 테이블 존재 초기에 삽입되었을 수 있기 때문에 정렬된 데이터인 경우가 많습니다.테이블에서 많은 삭제가 발생하지 않으면 주문된 것으로 보일 수 있습니다.(예를 들어, 작성일은 표 작성 자체만큼 과거로 거슬러 올라갈 수 있습니다).그러나 실제로는 이 테이블이 삭제가 많은 경우 Top N 행은 전혀 이와 같지 않을 수 있습니다.

결론은 BOOTN 레코드를 요구하는 사람은 실제로 무엇을 요구하는지도 모른다는 것입니다.아니면 최소한 그들이 요구하는 것과 BOTOM이 실제로 의미하는 것은 같지 않습니다.

그래서 --솔루션은 의뢰인의 실제 비즈니스 요구를 충족시킬 수 있습니다.그러나 최하위라는 기준을 충족하지 못합니다.

먼저, 다음을 사용하여 표의 원래 순서에 따라 하위 질의에 색인을 작성합니다.

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

이 할 은 당신이 해야 할 일은 당신이 거꾸로 입니다.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;

"Justin Ethier"가 현재 승인한 답변은 "Protector 1"이 지적한 정답이 아닙니다.

현재로선 저자가 질문한 BOTOM(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

저는 이것이 모든 상황에서 사용하기에 좋은 생각이라고 주장하는 것은 아니지만, 원하는 결과를 얻을 수 있습니다.

OFFSET FETCH 절을 사용할 수 있습니다.

SELECT COUNT(1) FROM COHORT; --Number of results to expect

SELECT * FROM COHORT 
ORDER BY ID
OFFSET 900 ROWS --Assuming you expect 1000 rows
FETCH NEXT 100 ROWS ONLY;

(Microsoft SQL Server용)

공식 문서: https://www.sqlservertutorial.net/sql-server-basics/sql-server-offset-fetch/

위의 "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

반환되는 행의 수를 알 필요가 없는 해결책을 생각해 냈습니다.

예를 들어, 최신 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]
SELECT TOP 10*from TABLE1 ORDER BY ID DESC

여기서 ID는 TABLE1의 프라이머리 키입니다.

SELECT columns FROM My_Table LIMIT 200 OFFSET (SELECT Count(*)-200 My_Table)

언급URL : https://stackoverflow.com/questions/1876606/how-to-select-bottom-most-rows

반응형