SQL:如何限制第一个找到的行的连接?

kku*_*ung 14 sql oracle join greatest-n-per-group

如何在两个表之间建立连接但限制为满足连接条件的第一行?

在这个简单的例子中,我想为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
Run Code Online (Sandbox Code Playgroud)

可能是Oracle提供了这样一个功能(性能是一个值得关注的问题).

0xd*_*xdb 11

这里的关键词是FIRST.您可以使用分析函数FIRST_VALUE或聚合构造FIRST.
对于FIRSTLAST性能更差从未经常和比同等更好FIRST_VALUELAST_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 */
;
Run Code Online (Sandbox Code Playgroud)

由于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 */
;
Run Code Online (Sandbox Code Playgroud)


Hus*_*vik 8

如果只需要单个值,则可以使用标量子查询:

SELECT
    id, name, (SELECT city FROM table_B WHERE id2 = table_A.id AND ROWNUM = 1) city
FROM
    table_A
Run Code Online (Sandbox Code Playgroud)


Mih*_*hai 3

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 ..
Run Code Online (Sandbox Code Playgroud)