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. 이것은 단계별로 설명 될 수 있습니다.

두 개의 열이 아래 표 참조 NAMEDT_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.