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

时间:2017-07-24 15:18:53

标签: oracle join plsql left-join

我试图在Oracle中使用LEFT JOIN连接两个表。我只需要包含来自"右边"的第一条记录。加入了表格。

请参阅以下示例:

表A

code | emp_no

101  | 11111
102  | 22222
103  | 33333
104  | 44444
105  | 55555

表B

code | city       | county

101  | City1      | Country1
101  | City2      | Country1
101  | City3      | Country1
102  | City4      | Country2
103  | City5      | Country3

预期输出:

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

我需要从表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
      )

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

我该怎么做?

由于

3 个答案:

答案 0 :(得分:3)

您可以将min() aggrenate功能与the keep (dense_rank first ...) syntax一起使用,以获得“{1}}匹配外连接表中的数据:

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               

你必须先定义什么'虽然意味着 - 我已经通过保留条款中的city, county订购了订单,但您可能还有另一个列,但未显示该列应该指示订单。

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

答案 1 :(得分:2)

在Oracle 12c上,您可以使用OUTER APPLYFETCH 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   

答案 2 :(得分:1)

使用row_number()函数并获取row_number() = 1

的记录
SELECT select a.code,
       a.emp_no,
       b.city,
       b.county
FROM   table_a a
       left join (SELECT code,
                         city,
                         county,
                         row_number()
                           over (
                             PARTITION BY code
                             ORDER BY city, county ) rn
                  FROM   table_b) b
              ON b.code = a.code
                 WHERE rn = 1 OR rn IS NULL;  

注意:从问题实际上这意味着什么仍然不清楚。

  

来自“正确”联合表的第一条记录