SQL: 처음 찾은 행에서 조인을 제한하는 방법은 무엇입니까?
두 테이블 간에 조인을 하되 조인 조건을 충족하는 첫 번째 행으로 제한하는 방법은 무엇입니까?
이 간단한 예에서는 table_A의 모든 행에 대해 조건을 만족시키는 table_B의 첫 번째 행을 구하고자 합니다.
select table_A.id, table_A.name, table_B.city
from table_A join table_B
on table_A.id = table_B.id2
where ..
table_A (id, name)
1, John
2, Marc
table_B (id2, city)
1, New York
1, Toronto
2, Boston
The output would be:
1, John, New York
2, Marc, Boston
Oracle이 이러한 기능을 제공할 수 있습니다(성능이 문제입니다).
여기서 키워드는 FIRST입니다.분석 기능을 사용할 수 있습니다.FIRST_VALUE
또는 골재 구조FIRST
.
위해서FIRST
또는LAST
성능은 결코 나쁘지 않으며 종종 동등한 성능보다 낫습니다.FIRST_VALUE
또는LAST_VALUE
불필요한 창 정렬이 없기 때문에 실행 비용이 절감됩니다.
select table_A.id, table_A.name, firstFromB.city
from table_A
join (
select table_B.id2, max(table_B.city) keep (dense_rank first order by table_B.city) city
from table_b
group by table_B.id2
) firstFromB on firstFromB.id2 = table_A.id
where 1=1 /* some conditions here */
;
12c 이후 도입된 연산자LATERAL
,게다가CROSS/OUTER APPLY
조인, 오른쪽에 상관된 하위 쿼리를 사용할 수 있도록 합니다.JOIN
절:
select table_A.id, table_A.name, firstFromB.city
from table_A
cross apply (
select max(table_B.city) keep (dense_rank first order by table_B.city) city
from table_b
where table_B.id2 = table_A.id
) firstFromB
where 1=1 /* some conditions here */
;
단일 값만 원하는 경우 스칼라 하위 쿼리를 사용할 수 있습니다.
SELECT
id, name, (SELECT city FROM table_B WHERE id2 = table_A.id AND ROWNUM = 1) city
FROM
table_A
쿼리:
SELECT a.id,
a.name,
b.city
FROM table_A a
INNER JOIN
( SELECT id2,
city
FROM (
SELECT id2,
city,
ROW_NUMBER() OVER ( PARTITION BY id2 ORDER BY NULL ) rn
FROM Table_B
)
WHERE rn = 1
) b
ON ( a.id = b.id2 )
--WHERE ...
출력:
ID NAME CITY
---------- ---- --------
1 John New York
2 Marc Boston
select table_A.id, table_A.name,
FIRST_VALUE(table_B.city) IGNORE NULLS
OVER (PARTITION BY table_B.id2 ORDER BY table_B.city) AS "city"
from table_A join table_B
on table_A.id = table_B.id2
where ..
Oracle 12c에는 드디어 새로운 교차/외부 적용 연산자가 등장하여 사용자가 요청한 사항을 해결 방법 없이 처리할 수 있습니다.
다음은 'SYS'로 시작하는 이름을 가진 사용자가 소유한 (아마도) 많은 개체 중 하나에 대해서만 사전 보기를 보는 예입니다.
select *
from (
select USERNAME
from ALL_USERS
where USERNAME like 'SYS%'
) U
cross apply (
select OBJECT_NAME
from ALL_OBJECTS O
where O.OWNER = U.USERNAME
and ROWNUM = 1
)
Oracle 11g 및 이전 버전에서는 동일한 결과를 얻기 위해 일반적으로 두 번째 테이블의 ID를 기반으로 두 번째 테이블을 전체 검색하는 해결 방법만 사용해야 하지만 테스트 용도의 경우 측면 연산자를 활성화하고 다른 연산자를 사용할 수 있습니다.
-- Enables some new features
alter session set events '22829 trace name context forever';
select *
from (
select USERNAME
from ALL_USERS
where USERNAME like 'SYS%'
) U,
lateral (
select OBJECT_NAME
from ALL_OBJECTS O
where O.OWNER = U.USERNAME
and ROWNUM = 1
);
이 솔루션은 일반 조인에서와 같이 전체 테이블을 사용하지만 첫 번째 행으로 제한됩니다.저는 다른 솔루션들이 하나의 필드만 사용하거나 큰 테이블에 성능 문제가 있기 때문에 충분하지 않아서 이 글을 올립니다.저는 오라클 전문가가 아니기 때문에 누군가 이를 개선할 수 있다면 기꺼이 당신의 버전을 사용하겠습니다.
select *
from tableA A
cross apply (
select *
from (
select B.*,
ROW_NUMBER() OVER (
-- replace this by your own partition/order statement
partition by B.ITEM_ID order by B.DELIVERYDATE desc
) as ROW_NUM
from tableB B
where
A.ITEM_ID=B.ITEM_ID
)
where ROW_NUM=1
) B
파티션을 사용하여 id2를 분리한 다음 r_num = 1을 가져갑니다.
SELECT A.ID, A.NAME, B.CITY
FROM TABLE_A A,
(SELECT ID2, CITY,
ROW_NUMBER() OVER (PARTITION BY ID2 ORDER BY ID2) AS R_NUM
FROM TABLE_B) B
WHERE A.ID = B.ID2
AND R_NUM = 1;
언급URL : https://stackoverflow.com/questions/35255271/sql-how-to-limit-a-join-on-the-first-found-row
'programing' 카테고리의 다른 글
Firebase Crashlytics에 매핑 파일을 업로드하는 방법은 무엇입니까? (0) | 2023.07.02 |
---|---|
응답에서 텍스트 읽기 (0) | 2023.07.02 |
spring-boot-starter-web과 spring-boot-starter-weblux는 함께 작동하지 않습니까? (0) | 2023.07.02 |
MongoDB의 실제 필드 유형 반환 (0) | 2023.07.02 |
디버깅 없이 잘못된 명령 오류를 발생시킨 어셈블리 명령 찾기 (0) | 2023.07.02 |