oracle中connect by 神奇的用法

? ? 在code的過(guò)程中曾經(jīng)遇到過(guò)一個(gè)神奇的問(wèn)題:

? ? 現(xiàn)在有多條火車(chē)線路,經(jīng)過(guò)了若干站點(diǎn),找出經(jīng)過(guò)P站點(diǎn)能直接到達(dá)的所有站點(diǎn)。

? ? 其中在數(shù)據(jù)庫(kù)中存儲(chǔ)的線路是分路段存儲(chǔ),格式是? ID? ?A_STATION? Z_STATION? 其他屬性略,比如? ? ?a->b->c->d->e->f->g 那么存儲(chǔ)的數(shù)據(jù) 為??

? ? ? ? 1? ?a? ? b

? ? ? ? 2? ?c? ? b

? ? ? ? 3? ? c? ? d

? ? ? ? ...

? ? 看出來(lái)了,分路段存儲(chǔ),但是又無(wú)序,不是嚴(yán)格按照? a->b , b->c , c->d 這樣存儲(chǔ)的,剛開(kāi)始的時(shí)候,我也沒(méi)有想過(guò)其他方法,直接在代碼中使用了遞歸來(lái)判斷,循環(huán)查詢數(shù)據(jù),但是發(fā)現(xiàn)這樣效率并不高,而且遞歸的過(guò)程中很容易出錯(cuò),這時(shí)候,我發(fā)現(xiàn)oracle中有一個(gè)connect by實(shí)現(xiàn)的遞歸查詢,于是打算使用一下。

? ? 使用過(guò)程中發(fā)現(xiàn)由于數(shù)據(jù)不是嚴(yán)格的有序排序,A,Z無(wú)序,無(wú)法直接使用,這時(shí),我動(dòng)了一個(gè)歪腦筋,由于表中數(shù)據(jù)量也不是太大,只有幾萬(wàn)條記錄,我能不能把表中所有數(shù)據(jù)翻轉(zhuǎn)一下,A,Z 變成 Z,A然后重命名為 A,Z,再使用union 拼接成兩倍記錄的新表,想到之后馬上就做,于是有了:

? ?? (select id,a_id,z_id

? ? ? ? ? ?from table

? ? ? ? ? ? ?union

? ? ? ? ? ? select id,z_id as a_id,a_id as z_id

? ? ? ? ? ?from table) t

? ? 這是一張新的表,里面的記錄是原表的兩倍,然后對(duì)這個(gè)表進(jìn)行connect by 遞歸查詢:

? ??????select *

? from (select id, a_id, z_id

? ? ? ? ? from table

? ? ? ? union

? ? ? ? select id, z_id as a_id, a_id as z_id

? ? ? ? ? from table) t

start with t.a_id = ?

connect by? prior t.z_id = t.a_id

? ? 哈哈,這下好了吧,解決了無(wú)序的問(wèn)題??墒切碌膯?wèn)題出現(xiàn)了,我一運(yùn)行,沒(méi)有報(bào)錯(cuò),可是數(shù)據(jù)怎么有問(wèn)題。重復(fù)了兩次?仔細(xì)一想,數(shù)據(jù)重復(fù)了兩次,這樣不但查詢出來(lái)的結(jié)果會(huì)有問(wèn)題,而且說(shuō)不定還會(huì)報(bào)無(wú)限遞歸調(diào)用的錯(cuò)誤(可能是我使用的ID正好,所有偶然的沒(méi)有報(bào)錯(cuò),不然會(huì)無(wú)限遞歸報(bào)錯(cuò))。這個(gè)怎么解決呢?

? ? 然后我查詢了一下網(wǎng)上oracle 的 connect by 使用的很多案例,發(fā)現(xiàn)了oracle的一個(gè)關(guān)鍵字“NOCYCLE”,還有嵌套使用的一個(gè)條件“connect_by_iscycle = 0”,限制了遞歸過(guò)程中不能成環(huán),然后再加上我自己生成的數(shù)據(jù)跟原始數(shù)據(jù)的id是相同的,那么我可以限制id只能出現(xiàn)一次,不能重復(fù)使用一條記錄遞歸“t.id <> t.id”經(jīng)過(guò)修改,最終的SQL成了下面這樣:

select *

? from (select id, a_id, z_id

? ? ? ? ? from table

? ? ? ? union

? ? ? ? select id, z_id as a_id, a_id as z_id

? ? ? ? ? from table) t

where connect_by_iscycle = 0

start with t.a_id = ?

connect by NOCYCLE prior t.z_id = t.a_id

? ? ? and prior t.id <> t.id

? ? 最終實(shí)現(xiàn)了需求,當(dāng)然,我這樣使用在很多時(shí)候是不合規(guī)的,有什么不對(duì)的,還請(qǐng)大家指出,只是這里是一種特殊的情況中的特殊用法,這種騷操作還是不要推廣的好。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容