1

背景:

我正在研究一个用于跟踪电线镜头的大型数据库。目前,数据库 (Oracle) 围绕三个主要表构建:

1) 地图详细信息表。定义特定地图的所有顶级细节,例如县/区/市。每张地图都由下表中使用的序列号唯一标识。

2) 走廊长度表。基本上,当乌鸦飞过时,电线有多长,以及该走廊是在公共土地上还是在私人土地上。因此,这里定义的镜头只是从 A 到 B 的距离。

3) 电线长度表。此表存储有关可以在给定走廊中运行的不同电线的信息。每个工作电压有一行。因此,一条走廊可能有若干长度的电线,例如;12KV、33KV、66KV。

(1) 中总会有一个映射记录,但 (2) 和 (3) 中的行数是任意的,并且 (2) 和 (3) 中的行数通常不匹配。

问题:

我正在寻找一种方法来加入这三个表,以便每个镜头只报告一次。这最好通过例子来说明。下面是一个示例记录集:

Map Details:
-------------------------------------------
| SERIAL_NO | CNTY | DIST | MAP_NO (Name) |
|-----------------------------------------|
|         1 |   33 |   88 | 123-4567-8    |
-------------------------------------------

Corridor Details:
------------------------------------
| SERIAL_NO | PROPRTY_CD | CORR_FT |
|----------------------------------|
|         1 |     PUBLIC |     100 |
|         1 |    PRIVATE |     200 |
------------------------------------

Wire Details
---------------------------------
| SERIAL_NO | OPER_KV | WIRE_FT |
|-------------------------------|
|         1 |      12 |     300 |
|         1 |      33 |     200 |
|         1 |      66 |     200 |
---------------------------------

我追求的最终输出将类似于以下内容:

--------------------------------------------------------------------------------------
| SERIAL_NO | CNTY | DIST | MAP_NO (Name) | PROPRTY_CD | CORR_FT | OPER_KV | WIRE_FT |
|------------------------------------------------------------------------------------|
|         1 |   33 |   88 | 123-4567-8    |     PUBLIC |     100 |      12 |     300 |
|         1 |   33 |   88 | 123-4567-8    |    PRIVATE |     200 |      33 |     200 |
|         1 |   33 |   88 | 123-4567-8    |       NULL |    NULL |      66 |     200 |
--------------------------------------------------------------------------------------

注意: 电线和走廊的镜头大部分时间都不匹配(为了简洁起见,这里没有显示电线倍增器等)。此外,与导线表(其中没有导线的走廊)相比,走廊表中的行数可能更多,反之亦然(其中有多条导线的走廊)。

我已经尝试了许多不同的方法来解决这个问题,但我似乎无法获得我想要的输出。我尝试过的每个连接都导致值被复制为或类似于以下内容:

BAD:
--------------------------------------------------------------------------------------
| SERIAL_NO | CNTY | DIST | MAP_NO (Name) | PROPRTY_CD | CORR_FT | OPER_KV | WIRE_FT |
|------------------------------------------------------------------------------------|
|         1 |   33 |   88 | 123-4567-8    |     PUBLIC |     100 |      12 |     300 |
|         1 |   33 |   88 | 123-4567-8    |     PUBLIC |     100 |      33 |     200 |
|         1 |   33 |   88 | 123-4567-8    |     PUBLIC |     100 |      66 |     200 |
|         1 |   33 |   88 | 123-4567-8    |    PRIVATE |     200 |      12 |     300 |
|         1 |   33 |   88 | 123-4567-8    |    PRIVATE |     200 |      33 |     200 |
|         1 |   33 |   88 | 123-4567-8    |    PRIVATE |     200 |      66 |     200 |
--------------------------------------------------------------------------------------

概括:

我为这个冗长的问题道歉,但解释我所追求的有点复杂。长话短说,我想并排列出两个子表中的所有行(无特定顺序),同时为两个表之间的行差异的列填充 NULL。先感谢您。

4

1 回答 1

2

The task in the way you set it up can be brute-forced in the following way

--pseudo-tables with sample data
with t_map  as (select 1 serial_no, 33 cnty,  88 dist, '12345678' map_no from dual),
 t_corr as (select 1 serial_no, 'PUBLIC' property_cd, 100 corr_ft from dual union all
            select 1, 'PRIVATE', 200 from dual),
 t_wire as (select 1 serial_no, 12 oper_kv, 300 wire_ft from dual union all 
            select 1, 33, 200 from dual union all
            select 1, 66, 200 from dual)
--query itself
select m.serial_no, m.cnty, m.dist, m.map_no, r.*
  from  t_map m join 
        (select nvl(c.serial_no, w.serial_no)  serial_no, c.property_cd, c.corr_ft, w.oper_kv, w.wire_Ft from (
                        (select t_corr.*, row_number() over(partition by serial_no order by serial_no) rn from t_corr) c 
              full join (select t_wire.*, row_number() over(partition by serial_no order by serial_no) rn from t_wire) w 
                     on c.serial_no = w.serial_no and (c.rn = w.rn)
                       )
        ) r on r.serial_no = m.serial_no;

However, if I were you I would concern about questions asked in comments to your initial post ;)

于 2012-05-18T19:02:15.380 回答