Oracle,重复记录使用" connect by"声明

时间:2016-04-11 14:46:33

标签: string oracle split

几乎是Oracle数据库的新手我很乐意寻求你的帮助。

我需要将字符串拆分为不同的记录,每个字符对应一个字符:

我有一个包含VARCHAR字段的查询,我需要将其拆分为多个字符

select
    MAPS.MAP_ID,
    HARD_BIN_LINES.LINE, HARD_BIN_LINES.BINS
from MAPS, HARD_BIN_LINES
where MAPS.MAP_ID = 9595435 and MAPS.MAP_ID = HARD_BIN_LINES.MAP_ID 
order by HARD_BIN_LINES.MAP_ID, HARD_BIN_LINES.LINE


MAP_ID  LINE    BINS
9595435 1       ÿÿÿÿÿÿÿÿÿÿÿþþþþÿÿÿÿÿÿÿÿÿÿÿ
9595435 2       ÿÿÿÿÿÿÿþþ       þþÿÿÿÿÿÿÿÿ
9595435 3       ÿÿÿÿÿþþ2           þÿÿÿÿÿÿ
9595435 4       ÿÿÿÿþ               þþÿÿÿÿ
9595435 5       ÿÿÿþ2                 þÿÿÿ
9595435 6       ÿÿþ                    þÿÿ
9595435 7       ÿÿþ2                   þÿÿ
9595435 8       ÿþþÿ                   þþÿ
9595435 9       ÿ2                      þÿ
9595435 10      þÿ                      þÿ
9595435 11      þ                        þ
9595435 12      ü                        þ
9595435 13      ü2                       þ
9595435 14      þ                        þ
9595435 15      þ                        ÿ
9595435 16      ÿþ             xx      þÿ
9595435 17      ÿþ                      þÿ
9595435 18      ÿÿþ                    þÿÿ
9595435 19      ÿÿþ                    þÿÿ
9595435 20      ÿÿÿþ                  þÿÿÿ
9595435 21      ÿÿÿÿþ               þþÿÿÿÿ
9595435 22      ÿÿÿÿÿþ      þ 2    þÿÿÿÿÿÿ
9595435 23      ÿÿÿÿÿÿÿþ þ  þþ    ÿÿÿÿÿÿÿÿ
9595435 24      ÿÿÿÿÿÿÿÿÿÿÿþþþþÿÿÿÿÿÿÿÿÿÿÿ

我的目标是将BINS字符串拆分成几个字母/记录,获得像这样的记录集

MAP_ID  LINE    LEVEL   CHR BINCODE
-------+-------+-------+---+--------
9595435 1       2       ÿ   255
9595435 1       3       ÿ   255
9595435 1       4       ÿ   255
9595435 1       5       ÿ   255
9595435 1       6       ÿ   255
9595435 1       7       ÿ   255
9595435 1       8       ÿ   255
9595435 1       9       ÿ   255
9595435 1       10      ÿ   255
9595435 1       11      ÿ   255
9595435 1       12      þ   254
9595435 1       13      þ   254
9595435 1       14      þ   254
9595435 1       15      þ   254
9595435 1       16      ÿ   255
9595435 1       17      ÿ   255
9595435 1       18      ÿ   255
9595435 1       19      ÿ   255
9595435 1       20      ÿ   255
9595435 1       21      ÿ   255
9595435 1       22      ÿ   255
9595435 1       23      ÿ   255
9595435 1       24      ÿ   255
9595435 1       25      ÿ   255
9595435 1       26      ÿ   255
-------+-------+-------+---+--------
9595435 2       2       ÿ   255
9595435 2       3       ÿ   255
9595435 2       4       ÿ   255
9595435 2       5       ÿ   255
9595435 2       6       ÿ   255
9595435 2       7       ÿ   255
9595435 2       8       þ   254
9595435 2       9       þ   254
9595435 2       10          1
9595435 2       11          1
9595435 2       12          10
9595435 2       13          1
9595435 2       14          13
9595435 2       15          17
9595435 2       16          1
9595435 2       17      þ   254
9595435 2       18      þ   254
9595435 2       19      ÿ   255
9595435 2       20      ÿ   255
9595435 2       21      ÿ   255
9595435 2       22      ÿ   255
9595435 2       23      ÿ   255
9595435 2       24      ÿ   255
9595435 2       25      ÿ   255
9595435 2       26      ÿ   25
-------+-------+-------+---+--------
(...)

如果我尝试用" CONNECT BY"来解决问题。声明我获得了许多重复记录,我无法理解为什么我的查询中没有错误:

with temp as (
    select
        MAPS.MAP_ID,
        HARD_BIN_LINES.LINE, HARD_BIN_LINES.BINS
    from MAPS, HARD_BIN_LINES
    where MAPS.MAP_ID = 9595435 and MAPS.MAP_ID = HARD_BIN_LINES.MAP_ID
    order by HARD_BIN_LINES.MAP_ID, HARD_BIN_LINES.LINE
)
select 
    MAP_ID, LINE, LEVEL,
    substr(BINS,level,1) as CHR, ASCII(substr(BINS,level,1)) as BINCODE
from temp
connect by level <= length(BINS)

1 个答案:

答案 0 :(得分:0)

temp结果集中的每一行都连接到其他每一行。您需要使用prior line = line子句将递归限制为同一行。但是你还需要避免循环;一种方法是在另一个prior子句中引用非确定性函数:

select 
    MAP_ID, LINE, LEVEL,
    substr(BINS,level,1) as CHR, ASCII(substr(BINS,level,1)) as BINCODE
from temp
connect by prior line = line
and prior dbms_random.value is not null
and level <= length(BINS);

从您发布的临时数据中获取623行。

如果您使用的是11gR2或更高版本,您还可以使用recursive subquery factoring

with temp as (
  select ...
),
r (MAP_ID, LINE, LVL, CHR, BINCODE) AS (
  select MAP_ID, LINE, 1, substr(BINS,1,1), ASCII(substr(BINS,1,1))
  from temp
  union all
  select t.MAP_ID, t.LINE, r.LVL + 1, substr(t.BINS,r.LVL + 1,1),
    ASCII(substr(BINS,r.LVL + 1,1))
  from r
  join temp t on t.MAP_ID = r.MAP_ID and t.LINE = r.LINE and length(t.BINS) > r.LVL
)
select *
from r;

得到相同的结果。