PL-SQL - 一对多关系左连接中的第一条记录

Igo*_*nov 1 oracle plsql join left-join

我正在尝试在 Oracle 中使用 LEFT JOIN 连接两个表。我只需要包含“正确”连接表中的第一条记录。

请参阅下面的示例:

表A

code | emp_no

101  | 11111
102  | 22222
103  | 33333
104  | 44444
105  | 55555
Run Code Online (Sandbox Code Playgroud)

表B

code | city       | county

101  | City1      | Country1
101  | City2      | Country1
101  | City3      | Country1
102  | City4      | Country2
103  | City5      | Country3
Run Code Online (Sandbox Code Playgroud)

预期输出:

code | emp_no | city      | county

101  | 11111  | City1     | Country1
102  | 22222  | City4     | Country2
103  | 33333  | City5     | Country3
104  | 44444  | NULL      | NULL
105  | 55555  | NULL      | NULL
Run Code Online (Sandbox Code Playgroud)

我需要从表 B 中选择第一个匹配的记录并忽略所有其他行。

上面的查询假设有效:

SELECT *
FROM TABLE_A a
   LEFT JOIN TABLE_B b ON b.CODE = a.CODE
      AND b.CODE = 
      (
         SELECT CODE
         FROM TABLE_B
         WHERE ROWNUM = 1
      )
Run Code Online (Sandbox Code Playgroud)

但我收到错误:ORA-01799: 列可能未外部连接到子查询

我怎样才能做到这一点?

谢谢

kro*_*lko 6

在 Oracle 12c 上,您可以使用OUTER APPLYandFETCH FIRST子句:

SELECT *
FROM tableA  a
OUTER APPLY (
   SELECT * FROM tableB b
   WHERE a.code = b.code
   ORDER BY city, county
   FETCH FIRST ROW ONLY
)

      CODE     EMP_NO       CODE CITY  COUNTY  
---------- ---------- ---------- ----- --------
       101      11111        101 City1 Country1
       102      22222        102 City4 Country2
       103      33333        103 City5 Country3
       104      44444                          
       105      55555   
Run Code Online (Sandbox Code Playgroud)


Ale*_*ole 5

您可以使用min()aggrenate函数keep (dense_rank first ...)语法来从外连接表“第一个”匹配的数据:

select a.code, a.emp_no,
  min(b.city) keep (dense_rank first order by city, county) as city,
  min(b.county) keep (dense_rank first order by city, county) as county
from table_a a
left join table_b b on b.code = a.code
group by a.code, a.emp_no
order by a.code, a.emp_no;

      CODE     EMP_NO CITY  COUNTY  
---------- ---------- ----- --------
       101      11111 City1 Country1
       102      22222 City4 Country2
       103      33333 City5 Country3
       104      44444               
       105      55555               
Run Code Online (Sandbox Code Playgroud)

不过,您必须定义“第一”的含义 - 我已经city, county在 keep 子句中使用 order by ,但是您可能还有另一列您没有显示应该指示顺序。

(您可以按 null 排序以使其有点随意,但这通常不是一个好主意,尤其是因为稍后运行相同的查询可能会为相同的数据提供不同的结果。)