【问题标题】:Oracle join returning too many rowsOracle join 返回太多行
【发布时间】:2021-05-29 04:07:11
【问题描述】:

我在 Oracle 19 中有以下选择语句:

select count(*) as facility_load_stg_cnt from facility_load_stg;

select count(*) as facility_cnt from facility;

select count(*) as loctn_typ_cnt from loctn_typ;

select count(*) as join_cnt from (
select f.facility_id, lt.loctn_typ_id
from facility_load_stg stg
inner join facility f on stg.facility_cd = f.facility_cd
inner join loctn_typ lt on stg.bldg = lt.loctn_typ_nm);

对象很简单,获取设施的 PK 和 loctn_typ (facility_id, loctn_typ_id) 以插入将建立关系的表中。

问题是当我运行上面的代码时,我得到了这些结果:


FACILITY_LOAD_STG_CNT
---------------------
                  987


FACILITY_CNT
------------
         645


LOCTN_TYP_CNT
-------------
          188


  JOIN_CNT
----------
      2905

为什么带有连接的 select 有 3 倍的 facility_load_stg 表的行?我确定我在做一些愚蠢的事情,我只是看不到它。

人们要求查看表格定义,以下是相关部分:

create table FACILITY_MAINT_DATA.FACILITY_LOAD_STG
(
    FACILITY_CD VARCHAR2(100) not null,
    BLDG VARCHAR2(100)
)

create table FACILITY_MAINT_DATA.FACILITY
(
    FACILITY_CD VARCHAR2(100),
    FACILITY_ID NUMBER(14) not null
        constraint PK_FACILITY
            primary key
)

create table FACILITY_MAINT_DATA.LOCTN_TYP
(
    LOCTN_TYP_ID NUMBER(14) default "FACILITY_MAINT_DATA"."LOCTN_TYP_ID_SEQ"."NEXTVAL" not null
        constraint PK_LOCTN_TYP
            primary key,
    LOCTN_TYP_NM VARCHAR2(100),
)

【问题讨论】:

  • 您的表定义是什么,您的数据是什么样的?据推测,您加入的不是主键。如果flt 中的多行与stg 中单行的连接条件匹配,则您的连接将生成比stg 中更多的行。
  • 我们无法回答,但可以推测。您没有解释 *_cd 是什么,以及为什么要加入它们而不是 *_id 列(如果这些是主键)。例如,几个设施可能具有相同的“代码”(猜测“cd”可能意味着什么),即使它们是不同的设施。在这种情况下,加入可能是错误的/不正确的/没有做你认为它做的事情。
  • 尝试类似 select facility_cd,count() from facility_cnt group by facility_cd;并从 loctn_typ_cnt 组中选择 loctn_typ_nm,count() by loctn_typ_nm; - 如果您看到 count > 1 的 facility_cd 或 loctn_typ_nm 值,那么您知道在这些列上从 facility_load_stg_cnt 连接可能会连接到这些表中的多行。

标签: oracle inner-join


【解决方案1】:

如果您加入并遇到您期望的更高计数,一般规则是加入键不是唯一的*

这里是一个简单的例子,复制了与你相同的结果(仅限于两个表)。

create table tab1 as
select rownum id, 
case when rownum <= 80 then 'CD_'||rownum else 'CD_X' end cd from dual connect by level <= 645;

create table tab2 as
select rownum id, 
case when rownum <= 80 then 'CD_'||rownum 
when rownum <= 85 then 'CD_X'
else 'CD_Y' end cd from dual connect by level <= 987;

select count(*) from tab1;

  COUNT(*)
----------
       645

select count(*) from tab2;

  COUNT(*)
----------
       987

select count(*) 
from tab1
join tab2
on tab1.cd = tab2.cd;

  COUNT(*)
----------
      2905

摘要将连接更改为使用唯一键或将连接限制为唯一的 CDcolumns。

【讨论】:

    【解决方案2】:

    感谢大家的 cmets,这让我看到了实际数据的详细信息,并且存在重复。现在我只需要弄清楚原因,只需要一些调查:)

    【讨论】:

      猜你喜欢
      • 2011-12-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-29
      • 2020-05-12
      • 1970-01-01
      相关资源
      最近更新 更多