如果您可以識別所有組及其起始set_id
,那麼您可以使用遞歸方法並在單個語句中執行此操作,而不是需要迭代填充表。但是,爲了提高速度/效率和資源消耗,您需要對這兩種方法進行基準測試 - 無論是針對您的數據量還是在系統的可用資源範圍內進行擴展,都需要進行驗證。
如果我的理解,當你決定開始您就可以使用查詢一次識別所有這些新組:
with t as (
select t1.type, t1.set_id, t1.min_value, t1.max_value,
t2.set_id as next_set_id, t2.min_value as next_min_value,
t2.max_value as next_max_value
from table1 t1
left join table1 t2 on t2.type = t1.type and t2.min_value > t1.max_value
where not exists (
select 1
from table1 t3
where t3.type = t1.type
and t3.max_value < t1.min_value
)
)
select t.type, t.set_id, t.min_value, t.max_value,
t.next_set_id, t.next_min_value, t.next_max_value,
row_number() over (order by t.type, t.min_value, t.next_min_value) as grp_id
from t
where not exists (
select 1 from t t2
where t2.type = t.type
and t2.next_max_value < t.next_min_value
)
order by grp_id;
棘手位這裏獲得所有三組a
,特別是二組以set_id = 1
開頭,但d
只有一個組。內部select(在CTE中)通過not exists
子句查找沒有較低非重疊範圍的集合,並且外連接到同一個表以獲取不重疊的下一個集合,爲您提供了兩個以set_id = 1
開頭的組,還有四個以set_id = 9
開頭。然後,外部選擇將忽略除第二個子句以外的最低非重疊項 - 但不必再次打到真正的表。
所以,讓你:
TYPE SET_ID MIN_VALUE MAX_VALUE NEXT_SET_ID NEXT_MIN_VALUE NEXT_MAX_VALUE GRP_ID
---- ------ ---------- ---------- ----------- -------------- -------------- ------
a 1 1 3 2 4 10 1
a 1 1 3 3 6 10 2
a 4 2 5 3 6 10 3
b 5 1 9 4
c 6 1 7 5
c 7 3 10 6
d 8 1 2 9 3 3 7
然後,您可以使用它作爲錨定構件在recursive subquery factoring clause:
with t as (
...
),
r (type, set_id, min_value, max_value,
next_set_id, next_min_value, next_max_value, grp_id) as (
select t.type, t.set_id, t.min_value, t.max_value,
t.next_set_id, t.next_min_value, t.next_max_value,
row_number() over (order by t.type, t.min_value, t.next_min_value)
from t
where not exists (
select 1 from t t2
where t2.type = t.type
and t2.next_max_value < t.next_min_value
)
...
如果你離開了r
CTE與和剛剛做你」 d得到相同的七個小組。
遞歸部件然後使用從該查詢以各組的下一個成員的下set_id
其範圍,並且重複外連接/不存在查找找到下一個(多個)集合再次;停車時沒有下一組不重疊:
...
union all
select r.type, r.next_set_id, r.next_min_value, r.next_max_value,
t.set_id, t.min_value, t.max_value, r.grp_id
from r
left join table1 t
on t.type = r.type
and t.min_value > r.next_max_value
and not exists (
select 1 from table1 t2
where t2.type = r.type
and t2.min_value > r.next_max_value
and t2.max_value < t.min_value
)
where r.next_set_id is not null -- to stop looking when you reach a leaf node
)
...
最後您有一個基於遞歸CTE得到你想要的列和指定的順序查詢:
...
select r.type, r.grp_id, r.set_id
from r
order by r.type, r.grp_id, r.min_value;
它得到:
TYPE GRP_ID SET_ID
---- ---------- ----------
a 1 1
a 1 2
a 2 1
a 2 3
a 3 4
a 3 3
b 4 5
c 5 6
c 6 7
d 7 8
d 7 9
d 7 10
d 7 11
SQL Fiddle demo。
如果您想要顯示每組的最小/最大值,並且可以跟蹤並顯示每組的最小/最大值。我只是顯示了問題的列,但是。
你的例子只有有兩個元素的結果。可以有兩個以上嗎? – 2014-11-14 19:32:36
是的!這只是爲了簡單。可能是從'1'到'10'的每個「值」都是一個單獨的集合,因此是一個單獨的元素。我會更新示例數據以顯示此內容。 – esa606 2014-11-14 19:35:18
我認爲你的過程很好,除了第1步和第2步。你可以用table1中的每一組初始化表。 – 2014-11-14 19:47:25