Oracle에서 최상위 1을 수행하려면 어떻게해야합니까?


251

다음은 어떻게합니까?

select top 1 Fname from MyTbl

에서 오라클 11g ?




3
'상위 1'을 원하는 순서대로 알려주시겠습니까?
— Andrew Wolfe

1
우선, DB 엔진에 의존해서는 안됩니다. 그런 것들을 알고 싶다면 시퀀서에 넣으십시오. 그렇게하면 삽입 된 순서대로 번호가 부여됩니다.
— FlyingGuy 2012

답변:


257

첫 번째로 선택한 행만 원하는 경우 다음을 수행 할 수 있습니다.

select fname from MyTbl where rownum = 1

분석 함수를 사용하여 최상위 x를 주문하고 가져갈 수도 있습니다.

select max(fname) over (rank() order by some_factor) from MyTbl

54
한 행만 원하고 어느 행을 신경 쓰지 않는 경우에 좋습니다. 가장 최근의 레코드와 같은 특정 행을 원한다면 Vash의 답변과 같은 하위 선택에서 정렬을 수행해야합니다. Oracle은 정렬 전에 행 번호를 할당합니다.
— Scott Bailey

4
@Scott p. 맞아요. 패트릭, 좋은 지적은 그 구문이 틀렸다고 생각합니다 정말 이상 KEEP (DENSE_RANK () 마지막 ...)해야한다
— mcpeterson

2
첫 번째 예제와 두 번째 예제의 차이점은 첫 번째 예제는 A 행 (순서가없는 모든 행)을 선택한다는 것입니다. 두 번째 예는 주문 내부 쿼리를 수행하지 않고 첫 번째 행의 값을 가져옵니다 (아래 예에 따라).
— JulesLt

3
MyTbl에서 선택 최대 (FNAME) 이상 (some_factor에 의해 순위 () 순서) : 올바르지에서의 구문
— 스테판 거버

1
@jclozano "오라클의 잘 알려지지 않은 기능"-이와 관련하여 나는달라고 간청한다. "잘 알려지지 않은 기능"은 모호함을 암시하는 경향이 있으므로 사용을 피해야한다고 제안 할 수 있기 때문입니다. 이것은 모호하지 않으며 사용을 피해서는 안됩니다.
— Sepster

166
SELECT *
  FROM (SELECT * FROM MyTbl ORDER BY Fname )
 WHERE ROWNUM = 1;

8
이 답변은 TOP 행을 올바르게 가져옵니다 (ROWNUM을 제한하기 전에 결과를 정렬합니다).
— JulesLt

이 답변은 정확한 번역이 아닙니다. 원래 쿼리에는 ORDER BY가 없으며 테이블의 모든 열을 반환하지도 않습니다.
— OMG Ponies

나는 정정되었다 (아래 참조). 시간이 다되면 투표를 전환합니다.
— JulesLt

7
@OMGPonies 예. 그러나 아마도 대부분의 사람들이 실제로 자신의 문제를 인터넷 검색을 통해이 페이지를 방문하기를 원합니다.
— NimChimpsky

4
이 스레드에서 반드시이기는 대답이어야합니다. 나는 top X그것을 바꿀 수 있다는 메모를 추가 할 수 있습니다WHERE ROWNUM <= X
— SomethingSomething

31

함께 오라클 12C (6 월 2013), 당신은 다음과 같이 사용할 수 있습니다.

SELECT * FROM   MYTABLE
--ORDER BY COLUMNNAME -OPTIONAL          
OFFSET 0 ROWS FETCH NEXT 1 ROWS ONLY

6
흥미로운 명령, 나는 여기에 12c를 사용하고 있으며 OFFSET 0 ROWS분명히 필요하지 않습니다. 당신은 FETCH NEXT 1 ROWS ONLY또는 FETCH FIRST ROW ONLY순서를 사용 하거나 중요 할 수 있습니다. 또는 단지를 사용하는 것과 같습니다 WHERE rownum = 1. 심지어 OUTER APPLY 명령으로 시도했으며 Ms-SQL의 TOP 함수처럼 작동했습니다.
— 라파엘 멀린

당신은 맞습니다 @RafaelMerlin. 귀하의 게시물을 보낸 후 OFFSET 0 ROWS가 필요하지 않다는 것을 알았습니다. 상위 X와 상위 Y 사이의 데이터를 검색 할 때 유용합니다.
— MSK


지금까지 중요한 결 측점이있는 지금까지는 좋았습니다 TIES. 버전 과 관계가있을 경우 이를 참조하십시오12c +12c -
— Barbaros Özhan

10

당신은 사용할 수 ROW_NUMBER()와 ORDER BY하위 쿼리 절과의 교환이 열을 사용 TOP N. 이것은 단계별로 설명 될 수 있습니다.

두 개의 열이 아래 표 참조 NAME및 DT_CREATED.

여기에 이미지 설명을 입력하십시오

에 관계없이 처음 두 날짜 만 NAME사용해야하는 경우 아래 쿼리를 사용할 수 있습니다. 논리는 쿼리 안에 작성되었습니다

-- The number of records can be specified in WHERE clause
SELECT RNO,NAME,DT_CREATED
FROM
(
    -- Generates numbers in a column in sequence in the order of date
    SELECT ROW_NUMBER() OVER (ORDER BY DT_CREATED) AS RNO,
    NAME,DT_CREATED
    FROM DEMOTOP
)TAB
WHERE RNO<3;

결과

여기에 이미지 설명을 입력하십시오

경우에 따라 TOP N각각에 대해 결과 를 선택해야합니다 NAME. 이 경우 하위 쿼리에서 절 PARTITION BY과 함께 사용할 수 있습니다 ORDER BY. 아래 쿼리를 참조하십시오.

-- The number of records can be specified in WHERE clause
SELECT RNO,NAME,DT_CREATED
FROM
(
  --Generates numbers in a column in sequence in the order of date for each NAME
    SELECT ROW_NUMBER() OVER (PARTITION BY NAME ORDER BY DT_CREATED) AS RNO,
    NAME,DT_CREATED
    FROM DEMOTOP
)TAB
WHERE RNO<3;

결과

여기에 이미지 설명을 입력하십시오


1
ROW_NUMBER ()를 사용하는 것이 주제 답변보다 더 정확한 해결책입니다. 이 솔루션 (및 max (field) 변형)의 한 가지 문제는 " 업데이트를 위해 select ... (select ROW_NUMBER () ...) ;"
— Alexo Po.

그리고 때로는 PL / SQL에서 매우 중요합니다 (죄송합니다. 5 분 이내에 이전 주석을 편집하지 못했습니다).
— Alexo Po.

이 경우 외부와 마찬가지로 CTE를 사용할 수 있습니다. 권리? @Alexo Po.
— Sarath Avanavu

나는 당신을 이해하지 못하는 것 같아요. for update 절은 ROWID가 Oracle에 의해 "쉽게"보존 될 때 사용될 수 있습니다. 따라서 그룹화 (및 분석 절 사용으로 인한 그룹화)는 실제 ROWID를 숨기고 행을 잠글 수 없습니다. 둘째, CTE ( with (select ... ) as 절)는이 문제를 전혀 바꾸지 않으며 CTE는 단지 쿼리를 읽고 지원하는 것을 목표로합니다. 권리? @Sarath Avanavu
— 알렉 소 포.

나 자신에 유의하십시오. ROWID 문제는 실제로 RNO <3 조건으로 인해 특히 발생합니다 .이 경우 RNO 값은 ROWID와 연결되지 않으므로 Oracle은 행을 잠글 수 없습니다.
— Alexo Po.

9

당신은 같은 것을 할 수 있습니다

    SELECT *
      FROM (SELECT Fname FROM MyTbl ORDER BY Fname )
 WHERE rownum = 1;

RANK 및 / 또는 DENSE_RANK 분석 함수를 사용할 수도 있지만 ROWNUM 이 가장 쉬운 방법 일 것입니다.


1
계급 등의 예를 들어 주
— 시겠습니까?

9
select * from (
    select FName from MyTbl
)
where rownum <= 1;

5

사용하다:

SELECT x.*
  FROM (SELECT fname 
          FROM MyTbl) x
 WHERE ROWNUM = 1

Oracle9i +를 사용하는 경우 ROW_NUMBER ()와 같은 분석 함수 를 사용할 수 있지만 ROWNUM과 같이 성능이 좋지 않습니다 .


1
좋은 대답이지만 작은 오타가 포함되어 있습니다. Oracle9i +가 8i가되어서는 안되는 곳은 어디입니까? download-west.oracle.com/docs/cd/A87860_01/doc/server.817/…
— Ian Carpenter

@carpenteri : 사실, 분석은 8i에서 가능했습니다. 세부 사항을 기억할 수는 없지만 9i까지는 일반 대중에게 분석이 제공되지 않았습니다.
— OMG Ponies

작은 의견-아래 Vash의 답변에는 내부 쿼리에 대한 ORDER BY가 포함되어 있습니다.이 값은 'first'가 아닌 fname의 TOP 값을 원할 경우 중요합니다 (첫 번째 행이 삽입 될 수 있음). 편집 할 가치가 있습니까?
— JulesLt

@JulesLt : OP에서 제공하는 쿼리에 ORDER BY가 포함되어 있지 않으므로 이것이 답변을 나타내며 Oracle 구문으로 정확하게 변환됩니다.
— OMG Ponies

SQL SERVER TOP 구문에 대한 나의 오해 (오류가 ROWNUM이 아니라 RANK의 FIRST와 유사하다고 잘못 추측했습니다). 투표함.
— JulesLt

3

테이블에서 첫 번째 행을 선택하고 테이블에서 한 행을 선택하려면 서로 다른 두 가지 작업이 필요하며 다른 쿼리가 필요합니다. 그렇게하는 방법에는 여러 가지가 있습니다. 그중 4 개는 다음과 같습니다.

먼저

select  max(Fname) from MyTbl;

둘째

select  min(Fname) from MyTbl;

제삼

select  Fname from MyTbl  where rownum = 1;

네번째

select  max(Fname) from MyTbl where rowid=(select  max(rowid) from MyTbl)

3

나는 같은 문제가 있었고이 솔루션으로 이것을 해결할 수 있습니다.

select a.*, rownum 
from (select Fname from MyTbl order by Fname DESC) a
where
rownum = 1

첫 번째 값을 갖기 전에 결과를 주문할 수 있습니다.

행운을 빕니다

당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.