Как сделать так, чтобы два очень похожих столбца из двух разных траблов показывались под одним и тем же первичным ключом в главной таблице - PullRequest
0 голосов
/ 14 декабря 2018

Итак, в моей базе данных есть две таблицы с именами VAL и VAL_SUB.Таблица первичного ключа / драйвера в этой ситуации представляет собой таблицу с именем MAIN (как показано ниже)

MAIN_ID    MAIN_NAME    CREATED_DT    Units
  1         Height      DEC-14-18     INches
  2         Weight      DEC-12-18     LBs

В настоящее время у меня есть процесс / задание, которое вычисляет значения для замены на «экстремальные», нулевые илипропущенные значения в таблице VAL.Таблица VAL будет содержать все исходные данные, которые были проанализированы (как показано ниже):

 VAL_ID     VAL      Hour          Date
   1        -87       01:00 AM      NOV-30-18
   2         8        02:00 AM      NOV-30-18
   3        18        03:00 AM      NOV-30-18

VAL_SUB будет содержать все значения, которые были обновлены / заменены с использованием вышеуказанной логики, но также и значения, которые былиоставлено нетронутым.

  VAL_SUB_ID     VAL         Hour          Date
      1          12          01:00 AM      NOV-30-18

Каждая из таблиц VAL и VAL_SUB будет иметь отдельную таблицу RELationship к таблице MAIN (как показано ниже)

VAL_MAIN_REL

     VAL_MAIN_ID    VAL_ID         MAIN_ID
         1            1               2
         2            2               2 
         3            3               1

VAL_SUB_MAIN_REL

     VAL_SUB_MAIN_ID    VAL_SUB_ID      MAIN_ID
         1              1               2

Мне нужен запрос, который показывает 'subbed' и исходные значения в одной таблице / строке (как показано ниже):

 MAIN_ID        ORIG_VAL       SUB_VAL       UNITS      HOUR        DATE
    1              18           null         Inches     03:00 AM    30-NOV-18
    2               8           null         LBS        02:00 AM    30-NOV-18
    2              -87           12          LBS        01:00 AM    30-NOV-18

Я пробовал следующее, ноон не выдает желаемый результат (вместо этого он возвращает нулевые значения как для столбцов orig val, так и для столбцов sub val). Нужно ли выполнять какую-либо группировку?:

 select m.main_id
      , v.val    as ORIG_VAL
      , sv.val   as SUB_VAL
      , m.units
      , v.hour
      , v.date
    from main m
    join VAL_MAIN_REL VMR on m.main_id = vmr.main_id
    join VAL V on VMR.val_id = V.val_id
    join VAL_SUB_MAIN_REL VSMR on vsmr.main_id = m.main_id
    join VAL_SUB VS on VSMR.VAL_ID = vs.VAL_SUB_ID;

Ответы [ 2 ]

0 голосов
/ 14 декабря 2018

Похоже, что вам нужно левое внешнее объединение, которое основано на отношении 'sub' и соответствующей дате / времени из двух таблиц:

select m.main_id,
  v.val as orig_val,
  vs.val as sub_val,
  m.units,
  v.hour,
  v.date
from main m
join val_main_rel vmr on vmr.main_id = m.main_id
join val v on v.val_id = vmr.val_id
left join val_sub_main_rel vsmr on vsmr.main_id = m.main_id
left join val_sub vs on vs.val_sub_id = vsmr.val_sub_id
  and vs.date_ = v.date
  and vs.hour = v.hour;

Быстрая демонстрация с CTE для ваших примеров данныхс колонкой «date», переименованной в «date_», поэтому это действительный идентификатор:

-- CTEs for sample data, with 'date_' instead of 'date'
with main (main_id, main_name, created_dt, units) as (
  select 1, 'Height', date '2018-12-14', 'INches' from dual
  union all select 2, 'Weight', date '2018-12-12', 'LBs' from dual
),
val (val_id, val, hour, date_) as (
  select 1, -87, '01:00 AM', date '2018-11-30' from dual
  union all select 2, 8, '02:00 AM', date '2018-11-30' from dual
  union all select 3, 18, '03:00 AM', date '2018-11-30' from dual
),
val_sub (val_sub_id, val, hour, date_) as (
  select 1, 12, '01:00 AM', date '2018-11-30' from dual
),
val_main_rel (val_main_id, val_id, main_id) as (
  select 1, 1, 2 from dual
  union all select 2, 2, 2 from dual
  union all select 3, 3, 1 from dual
),
val_sub_main_rel (val_sub_main_id, val_sub_id, main_id) as (
  select 1, 1, 2 from dual
)
-- actual query
select m.main_id,
  v.val as orig_val,
  vs.val as sub_val,
  m.units,
  v.hour,
  v.date_
from main m
join val_main_rel vmr on vmr.main_id = m.main_id
join val v on v.val_id = vmr.val_id
left join val_sub_main_rel vsmr on vsmr.main_id = m.main_id
left join val_sub vs on vs.val_sub_id = vsmr.val_sub_id
  and vs.date_ = v.date_
  and vs.hour = v.hour;
   MAIN_ID   ORIG_VAL    SUB_VAL UNITS  HOUR     DATE_     
---------- ---------- ---------- ------ -------- ----------
         2        -87         12 LBs    01:00 AM 2018-11-30
         2          8            LBs    02:00 AM 2018-11-30
         1         18            INches 03:00 AM 2018-11-30

Множество внешних объединений и дублированных записей main_id, которые есть в ваших фактических val_sub таблицы сговорились сделать нежелательные совпадения, как вы описали в комментарии.Существует совпадение с таблицей отношений vsmr, но не с таблицей vs, если учитывать дату / час, но первого сопоставления с внешним соединением достаточно для создания дополнительных нежелательных строк в выводе.

С измененным CTE, имеющим второе вспомогательное значение:

-- CTEs for sample data, with 'date_' instead of 'date'
with main (main_id, main_name, created_dt, units) as (
  select 1, 'Height', date '2018-12-14', 'INches' from dual
  union all select 2, 'Weight', date '2018-12-12', 'LBs' from dual
),
val (val_id, val, hour, date_) as (
  select 1, -87, '01:00 AM', date '2018-11-30' from dual
  union all select 2, 8, '02:00 AM', date '2018-11-30' from dual
  union all select 3, 18, '03:00 AM', date '2018-11-30' from dual
),
val_sub (val_sub_id, val, hour, date_) as (
  select 1, 12, '01:00 AM', date '2018-11-30' from dual
  -- extra row added below
  union all select 2, 13, '02:00 AM', date '2018-11-30' from dual
),
val_main_rel (val_main_id, val_id, main_id) as (
  select 1, 1, 2 from dual
  union all select 2, 2, 2 from dual
  union all select 3, 3, 1 from dual
),
val_sub_main_rel (val_sub_main_id, val_sub_id, main_id) as (
  select 1, 1, 2 from dual
  -- extra row added below
  union all select 2, 2, 2 from dual
)
...

, исходный запрос получает:

   MAIN_ID   ORIG_VAL    SUB_VAL UNITS  HOUR     DATE_     
---------- ---------- ---------- ------ -------- ----------
         2        -87         12 LBs    01:00 AM 2018-11-30
         2          8         13 LBs    02:00 AM 2018-11-30
         2          8            LBs    02:00 AM 2018-11-30
         1         18            INches 03:00 AM 2018-11-30
         2        -87            LBs    01:00 AM 2018-11-30

Так что я думаю, что вам нужно устранить их с помощью подзапроса,так что вместо этого вы можете сделать одно внешнее объединение:

select m.main_id,
  v.val as orig_val,
  vsx.val as sub_val,
  m.units,
  v.hour,
  v.date_
from main m
join val_main_rel vmr on vmr.main_id = m.main_id
join val v on v.val_id = vmr.val_id
left join (
  select vsmr.main_id, vs.val, vs.date_, vs.hour
  from val_sub_main_rel vsmr
  join val_sub vs on vs.val_sub_id = vsmr.val_sub_id
) vsx on vsx.main_id = m.main_id
and vsx.date_ = v.date_
and vsx.hour = v.hour;

, что дает более разумный результат:

   MAIN_ID   ORIG_VAL    SUB_VAL UNITS  HOUR     DATE_     
---------- ---------- ---------- ------ -------- ----------
         2        -87         12 LBs    01:00 AM 2018-11-30
         2          8         13 LBs    02:00 AM 2018-11-30
         1         18            INches 03:00 AM 2018-11-30
0 голосов
/ 14 декабря 2018

Присоединяйтесь к одной таблице за раз, используя левое соединение

SELECT m.main_id, v.val as ORIG_VAL, sv.val as SUB_VAL, m.units, v.hour, v.date
FROM main m
LEFT JOIN VAL_MAIN_REL vm ON vm.main_id = m.main_id 
JOIN val v ON vm.val_id = v.val_id 
LEFT JOIN val_sub_main_rel sm ON sm.main_id = m.main_id 
JOIN val_sub sv ON sm.val_sub_id = sv.val_sub_id 
WHERE v.hour = sv.hour 
  AND v.date = sv.date
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...