Sql 从多个属性表中收集历史数据

Sql 从多个属性表中收集历史数据,sql,database,oracle,database-design,Sql,Database,Oracle,Database Design,我有一套设计得非常糟糕的数据库表,其中包含船只的数据。船舶属性被拆分为各自的表格船舶名称、长度、马力等。当船舶更新时,我们会在相应的属性表格中插入一条新记录,并注明生效日期,以便我们可以保留历史记录 我需要将这些数据拉入一个平面对象,该对象显示船只在历史中的样子。因此,如果名称和长度都在同一天编辑,那么当天只有一条记录。 请参考以下内容,更好地解释现有数据和预期结果 现有数据库表 预期结果 我继承了此数据库,目前无法对其设计进行更改。帮助我们帮助您-请共享表定义、一些示例数据以及您希望获得的该示

我有一套设计得非常糟糕的数据库表,其中包含船只的数据。船舶属性被拆分为各自的表格船舶名称、长度、马力等。当船舶更新时,我们会在相应的属性表格中插入一条新记录,并注明生效日期,以便我们可以保留历史记录

我需要将这些数据拉入一个平面对象,该对象显示船只在历史中的样子。因此,如果名称和长度都在同一天编辑,那么当天只有一条记录。 请参考以下内容,更好地解释现有数据和预期结果

现有数据库表

预期结果


我继承了此数据库,目前无法对其设计进行更改。

帮助我们帮助您-请共享表定义、一些示例数据以及您希望获得的该示例结果。@Mureinik我添加了一个从原始帖子中删除的图表。
-- Your Test Data
with vessel(id, cg, modified_date) as
 (select 1, 123, to_date('01012000', 'DDMMYYYY') from dual),
vessel_name(id, name, modified_date) as
 (select 1, 'Sea Queen', to_date('01012000', 'DDMMYYYY')
    from dual
  union all
  select 1, 'Sea King', to_date('01012001', 'DDMMYYYY')
    from dual
  union all
  select 1, 'Sea Goodess', to_date('03012005', 'DDMMYYYY')
    from dual),
vessel_horsepower(id, hp, modified_date) as
 (select 1, 50, to_date('02012000', 'DDMMYYYY')
    from dual
  union all
  select 1, 75, to_date('01012003', 'DDMMYYYY')
    from dual
  union all
  select 1, 110, to_date('03012005', 'DDMMYYYY')
    from dual)

-- Select:
select m.id,
       -- determine value of table "vessel" for current id, modified_date 
       (select cg
          from vessel n
         where n.id = m.id
           and n.modified_date =
               (select max(nn.modified_date)
                  from vessel nn
                 where nn.id = n.id
                   and nn.modified_date <= m.modified_date)),
       -- determine value of table "vessel_name" for current id, modified_date 
       (select name
          from vessel_name n
         where n.id = m.id
           and n.modified_date =
               (select max(nn.modified_date)
                  from vessel_name nn
                 where nn.id = n.id
                   and nn.modified_date <= m.modified_date)),
       -- determine value of table "vessel_horsepower" for current id, modified_date 
       (select hp
          from vessel_horsepower n
         where n.id = m.id
           and n.modified_date =
               (select max(nn.modified_date)
                  from vessel_horsepower nn
                 where nn.id = n.id
                   and nn.modified_date <= m.modified_date)),
       m.modified_date
  from -- collect all modified_dates of an id:
        (select v.id, v.modified_date
           from vessel v
         union
         select v.id, v.modified_date
           from vessel_name v
         union
         select v.id, v.modified_date
           from vessel_horsepower v) m;
Vessel_History  
|------------|------------|------------|------------|----------------|  
| vessel_id  |     CG#    |    name    |     HP     | effective_Date |  
|------------|------------|------------|------------|----------------|  
|     1      |     123    | Sea Queen  |    NULL    |   1/1/2000     |  
|------------|------------|------------|------------|----------------|  
|     1      |     123    | Sea Queen  |     50     |   2/1/2000     |  
|------------|------------|------------|------------|----------------|  
|     1      |     123    | Sea King   |     50     |   1/1/2001     |  
|------------|------------|------------|------------|----------------|  
|     1      |     123    | Sea King   |     75     |   1/1/2003     |  
|------------|------------|------------|------------|----------------|  
|     1      |     123    |Sea Goddess |     115    |   3/1/2005     |  
|------------|------------|------------|------------|----------------|  
-- Your Test Data
with vessel(id, cg, modified_date) as
 (select 1, 123, to_date('01012000', 'DDMMYYYY') from dual),
vessel_name(id, name, modified_date) as
 (select 1, 'Sea Queen', to_date('01012000', 'DDMMYYYY')
    from dual
  union all
  select 1, 'Sea King', to_date('01012001', 'DDMMYYYY')
    from dual
  union all
  select 1, 'Sea Goodess', to_date('03012005', 'DDMMYYYY')
    from dual),
vessel_horsepower(id, hp, modified_date) as
 (select 1, 50, to_date('02012000', 'DDMMYYYY')
    from dual
  union all
  select 1, 75, to_date('01012003', 'DDMMYYYY')
    from dual
  union all
  select 1, 110, to_date('03012005', 'DDMMYYYY')
    from dual)

-- Select:
select m.id,
       -- determine value of table "vessel" for current id, modified_date 
       (select cg
          from vessel n
         where n.id = m.id
           and n.modified_date =
               (select max(nn.modified_date)
                  from vessel nn
                 where nn.id = n.id
                   and nn.modified_date <= m.modified_date)),
       -- determine value of table "vessel_name" for current id, modified_date 
       (select name
          from vessel_name n
         where n.id = m.id
           and n.modified_date =
               (select max(nn.modified_date)
                  from vessel_name nn
                 where nn.id = n.id
                   and nn.modified_date <= m.modified_date)),
       -- determine value of table "vessel_horsepower" for current id, modified_date 
       (select hp
          from vessel_horsepower n
         where n.id = m.id
           and n.modified_date =
               (select max(nn.modified_date)
                  from vessel_horsepower nn
                 where nn.id = n.id
                   and nn.modified_date <= m.modified_date)),
       m.modified_date
  from -- collect all modified_dates of an id:
        (select v.id, v.modified_date
           from vessel v
         union
         select v.id, v.modified_date
           from vessel_name v
         union
         select v.id, v.modified_date
           from vessel_horsepower v) m;