如何使两个不同的三叉戟中的两个非常相似的列显示在主表的同一主键下

时间:2018-12-14 14:19:42

标签: sql oracle

所以我的数据库中有两个名为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表将分别具有一个与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列均返回null)是否需要进行某种分组?:

 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 :(得分:1)

使用左联接一次联接一个表

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

答案 1 :(得分:1)

您似乎想要左外部联接,该联接基于两个表中的“ 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_”,因此它是有效的标识符:

-- 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