2010-10-19 20 views
1

對垃圾問題標題抱歉。我有一個表SET_DEFINITIONS這樣的:如何編寫一個過程來查找這樣的一組行?

SETKEY  NOT NULL NUMBER(38) 
SETENTRY NOT NULL NUMBER(38) 

這裏的想法是,行定義組數字。例如,表格可以包含行:

1 2 
1 4 
2 1 
2 2 

這意味着集合1是{2,4},集合2是{1,2}。我想編寫一個函數

function selectOrInsertSet(table of number(38) numbers) return number(38) 

這將返回一組的鍵與相同的成員作爲表通過(或建立這樣一套,如果不存在的話)。在PL/SQL中執行此操作的好方法是什麼?

編輯:我目前工作的解決方案是這樣的(我不知道它會工作):

  1. 選擇具有第一個元素到一些集合c中所有鍵
  2. 通過與含有其他元素的連續組密鑰相交細化類集c

回答

2

您可以使用每個集合和數字集合之間的完整外連接來查看它們是否相同。這個函數是:

function selectOrInsertSet(numbers number_tt) return number 
is 
    l_diff number; 
    l_retval number; 
begin 
    for r in (select distinct setkey from set_definitions) 
    loop 
    with d as (select column_value from table(numbers)), 
      s as (select setentry from set_definitions where setkey=r.setkey) 
    select count(*) 
    into l_diff 
    from s 
    full outer join d on d.column_value = s.setentry 
    where s.setentry is null or d.column_value is null; 

    if l_diff = 0 then 
     l_retval := r.setkey; 
     exit; 
    end if; 
    end loop; 

    return l_retval; 
end; 

如果找到了,否則返回null這將返回setkey的。

我還沒有實現關於創建一個新的集合的部分,如果沒有發現,但應該很容易。我個人不喜歡有副作用的函數(在這種情況下,將行插入表中)。

+0

我喜歡用表的想法(數字),而不是我創造的方式一個全球臨時表。我做了一個直接的內部連接,並且對不知道set_definitions大小的匹配元素進行了成員計數檢查。也想知道處理多個匹配,但函數返回是一個單一的數字,所以可能不是一個要求。 – 2010-10-19 15:24:30

0

快速的方式找到交集可能是創建一個全局臨時表,並與TA傳遞填充它數字。然後,您可以使用SET_DEFINITIONS加入此表以查找所有可能的匹配項。您需要檢查每個匹配集中的總數以消除超集。

創建一些基本的表...

create table set_definitions (
    setkey number, 
    setentry number, 
    constraint pk_set_definitions primary key (setkey, setentry) 
    ); 

insert into set_definitions values (1,2); 
insert into set_definitions values (1,4); 
insert into set_definitions values (2,1); 
insert into set_definitions values (2,2); 
insert into set_definitions values (3,1); 
insert into set_definitions values (3,2); 
insert into set_definitions values (3,3); 

創建一個全局臨時表來保存傳遞值:

create global temporary table tmp_setentry (
    setentry number, 
    constraint pk_tmp_setentry primary key (setentry)); 

insert into tmp_setentry values (1); 
insert into tmp_setentry values (2); 

加入與set_definitions找到匹配的組(S):

select 
    setkey 
from 
    (
    select 
     setkey, 
     count(*) num_matches, 
     (select count(*) from set_definitions where setkey = s.setkey) 
      num_set_entries, 
     (select count(*) from tmp_setentry) num_entries 
    from 
     set_definitions s 
      inner join tmp_setentry t on t.setentry = s.setentry 
    group by 
     setkey 
    ) 
where 
    num_matches = num_entries 
and num_set_entries = num_entries 

--> 2 (3 is dropped as a superset) 

希望這會有所幫助。

0

Oracle 11g引入了LISTAGG函數,可以根據需要使用它。 以下面的例子爲理念,因爲我不是很熟悉Oracle,但它應該有可能是一些小的修改工作):

Create table set_definitions (setkey int, setentry int); 
Create table searchFor (setentry int); 

insert into set_definitions values (1,4); 
insert into set_definitions values (2,1); 
insert into set_definitions values (2,2); 
insert into set_definitions values (3,1); 
insert into set_definitions values (3,2); 
insert into set_definitions values (3,3); 

Insert Into searchFor Values (1); 
Insert into searchFor Values (2); 

With Prepare as 
(
Select setkey, LISTAGG(setentry, ',') WITHIN GROUP (ORDER BY setentry) as EntryList 
    From set_definitions  
Group by setkey 
Having Count(*)=(Select Count(*) From searchFor) -- Just to eliminate obvious ones 
) 
Select setkey 
    from Prepare 
Where EntryList = (Select LISTAGG(setentry, ',') WITHIN GROUP (ORDER BY setentry) From searchFor); 
相關問題