如何在Oracle中将连接操作减少到单行?

时间:2016-10-13 15:49:11

标签: oracle join

出于问题的目的,此示例是发明的

SELECT 
    PR.PROVINCE_NAME 
    ,CO.COUNTRY_NAME
FROM
    PROVINCE PR
    JOIN COUNTRY CO ON CO.COUNTRY_ID=PR.COUNTRY_ID
WHERE
    PR.PROVINCE_ID IN (1,2)

假设COUNTRY_ID不是Country表中的主键,而Country表上的上述连接可能返回多行。我们不知道有多少行,我们不关心为什么有多行。我们只想加入其中一个,所以我们每个省都会得到一行。

我为连接尝试了子查询,但无法通过PR.COUNTRY_ID传递给Oracle 11.2。还有其他方法可以实现这一目标吗?

2 个答案:

答案 0 :(得分:0)

如果您有Oracle 12c,则可以在联接中使用LATERAL视图。像这样:

SELECT
    PR.PROVINCE_NAME 
    ,CO.COUNTRY_NAME
FROM
    PROVINCE PR
    CROSS JOIN LATERAL ( 
       SELECT * FROM COUNTRY CO 
       WHERE CO.COUNTRY_ID=PR.COUNTRY_ID 
       FETCH FIRST 1 ROWS ONLY) CO 
WHERE
    PR.PROVINCE_ID IN (1,2) 

Oracle 11.2更新

在Oracle 11.2中,您可以使用这些内容。根据{{​​1}}的大小以及每COUNTRY个重复的数量,它可以比12c方法表现更好或更好。 (缓冲区越少,但需要更多内存)。

COUNTRY_ID

答案 1 :(得分:0)

处理没有PK的表的典型安全方法是使用唯一索引(重复行的row_numer)扩展重复列

在你的情况下,这将是:

with COUNTRY_UNIQUE as (
select COUNTRY_ID, 
row_number() over (partition by COUNTRY_ID  order by COUNTRY_NAME) rn,
COUNTRY_NAME
from country)
select * from COUNTRY_UNIQUE 
order by COUNTRY_ID, rn;

导致

COUNTRY_ID         RN COUNTRY_NAME
---------- ---------- ------------
         1          1 C1           
         2          1 C2           
         2          2 C3

COUNTRY_IDRN的组合是唯一的,因此如果仅约束RN = 1,则COUNTRY_ID是唯一的。 您可以定义重复记录的顺序并用它来控制选择 - 在我们的例子中,我们选择最小的COUNTRY_NAME。

整个联接使用此子查询并限制RN = 1

上的国家/地区
with COUNTRY_UNIQUE as (
select COUNTRY_ID, 
row_number() over (partition by COUNTRY_ID  order by COUNTRY_NAME) rn,
COUNTRY_NAME
from country)
SELECT 
    PR.PROVINCE_NAME 
    ,CO.COUNTRY_NAME
FROM
    PROVINCE PR
    JOIN COUNTRY_UNIQUE CO ON CO.COUNTRY_ID=PR.COUNTRY_ID
WHERE
    PR.PROVINCE_ID IN (1,2) 
    AND CO.RN = 1;  /* consider only unique countries */