#oracle #inner-join
#Oracle #inner-join
Вопрос:
У меня есть следующие параметры выбора в 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 для facility и loctn_typ (facility_id, loctn_typ_id) для вставки в таблицу, которая будет строить отношения.
Проблема в том, что когда я запускаю приведенный выше код, я получаю следующие результаты:
FACILITY_LOAD_STG_CNT
---------------------
987
FACILITY_CNT
------------
645
LOCTN_TYP_CNT
-------------
188
JOIN_CNT
----------
2905
почему выбор с соединением в 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),
)
Комментарии:
1. Каковы ваши определения таблиц и как выглядят ваши данные? Предположительно, вы присоединяетесь к чему-то, кроме первичного ключа. Если несколько строк в
f
или вlt
соответствуют критериям объединения для одной строки вstg
, ваше объединение будет генерировать больше строк, чем вstg
.2. Мы не можем ответить, но мы можем строить предположения. Вы не объяснили, что это за
*_cd
вещи и почему вы объединяетесь с ними вместо*_id
столбцов, если это первичные ключи. Например, несколько объектов могут иметь один и тот же «код» (догадываясь, что может означать «cd»), даже если они являются разными объектами. В этом случае соединение, вероятно, неправильное / неправильное / не делает то, что вы думаете.3. Попробуйте что-то вроде select facility_cd,count( ) из facility_cnt group с помощью facility_cd; и выберите loctn_typ_nm,count( ) из loctn_typ_cnt group с помощью loctn_typ_nm; — если вы видите значение facility_cd или loctn_typ_nm со значением count> 1, то вы знаете, что соединение из facility_load_stg_cnt в этих столбцах может присоединяться к нескольким строкам вэти таблицы.
Ответ №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
Сводка измените объединение, чтобы использовать уникальные ключи, или ограничьте объединение только такими CD
уникальными столбцами.
Ответ №2:
Спасибо всем за комментарии, которые заставили меня детально рассмотреть фактические данные и выявить дублирование. Теперь мне просто нужно выяснить, почему, просто нужно провести небольшое расследование 🙂