Oracle,使用“connect by”语句重复记录
Posted
技术标签:
【中文标题】Oracle,使用“connect by”语句重复记录【英文标题】:Oracle, duplicate records using "connect by" statement 【发布时间】:2016-04-11 14:46:32 【问题描述】:作为 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)
【问题讨论】:
Connect by 只能用于递归(猪耳朵)自引用外键关系。连接语法是:先连接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;
得到相同的结果。
【讨论】:
以上是关于Oracle,使用“connect by”语句重复记录的主要内容,如果未能解决你的问题,请参考以下文章
Oracle PL/SQL CONNECT BY PRIOR ... SQL Server 中的 START WITH 语句