2015-06-04 47 views
2

我需要模擬人羣,我無法找到一種方法來設計表格來高效地完成它。我如何模擬人羣?

組可以被認爲是集合,一個或多個人的無序集合,每個組應該由其組件唯一標識。

編輯:一個人可以是多個組的一部分。

我的第一次嘗試看起來像這樣。 包含系統管理的所有「人員」的表格。

table Groups(
    group_id int, 
    group_name varchar, 
    (other data...) 
) 

,並與個人和羣體

table gropus_persons (
    person_id int, 
    group_id in 
) 

之間的關聯表這樣的設計不符合此合身:

table Persons(
    id int, 
    name varchar, 
    (other data...) 
) 

包含組和所有組屬性表因爲很難編寫查詢來從組件列表中檢索組標識符。

我能想出發現由人組成的小組唯一的查詢(1,2,3)看起來是這樣的:

select * 
from groups g 
where 
    g.group_id in (select group_id from gropus_persons where person_id = 1) 
    and g.group_id in (select group_id from gropus_persons where person_id = 2) 
    and g.group_id in (select group_id from gropus_persons where person_id = 3) 
    and not exists (select 1 from gropus_persons where group_id = g.group_id and person_id not in (1,2,3)) 

的問題是,部件的數量是可變的,所以我只能使用動態生成的查詢,並在每次需要查找新組時爲每個組件添加子查詢。

有沒有更好的解決方案?

謝謝您的幫助!

+1

搜索關於關係部門的變體。 – philipxy

+0

如果我告訴過你,個人和團體真的是一個人呢? (請參閱派對模特) –

+0

如果兩個小組由同一個人組成,該怎麼辦?也就是說,如果真的有這些人,你是否真的想要這個團體?更一般地說,人們如何組織成團體的限制是什麼?也就是說,groups_persons(除了大概是FKs還是Persons和Groups)還有什麼限制嗎? – philipxy

回答

-1

這個怎麼樣,我覺得模式是一樣的你,不知道:

create table Groups(
    group_id int primary key, 
    group_name varchar(100) 
); 

create table Persons(
    person_id int primary key, 
    name varchar 
); 


create table Membership(
    group_id int REFERENCES Groups (group_id), 
    person_id int REFERENCES Persons (person_id) 
); 


INSERT INTO Persons 
VALUES (1, 'p1'), 
     (2, 'p2'), 
     (3, 'p2'), 
     (4, 'p2'); 

INSERT INTO Groups 
VALUES (1, 'group1'), 
     (2, 'group2'); 

INSERT INTO Membership 
VALUES (1, 1), 
     (1, 2), 
     (2, 2), 
     (1, 3); 

然後選擇:

select p.name, g.group_name 
from Persons as p 
join Membership as m on p.person_id = m.person_id 
join Groups as g on g.group_id = m.group_id 
where m.group_id in (1, 2); 

顯然數據就需要進行調整,以適應你的。

0

您需要按「羣組」分組並統計您收到的點擊次數。爲此,您只需要十字路口表:

select GroupID, count(*) as MemberCount 
from GroupsPersons 
where PersonID in(1, 2, 3) 
group by GroupID 
having count(*) = 3; 

問題出在使此查詢適用於不同的人員ID值列表。你似乎已經意識到這將需要動態SQL,僞代碼將是這個樣子:

stmt := 'select GroupID, count(*) as MemberCount ' 
    || 'from GroupsPersons ' 
    || 'where PersonID in(' || CSVList || ') ' 
    || 'group by GroupID ' 
    || 'having count(*) = ' || length(CSVList); 

你必須要警惕的一個潛在的缺陷是,如果在列表中的相同的ID重複。例如:CSVList := '1, 2, 3, 2';

這將生成一個正確的count(*)值3,但having子句將查找4。

0

另一個需要考慮的解決方案是在Alpha序列中對/人類身份證集進行pivot/xpath並將其存儲在組表中,並將該字符串與目標進行比較。

對於您的示例,您將使用Select group_id from groups where personIDs = '1,2,3,'

+1

您可以在查詢中即時生成以逗號分隔的人員ID列表,並單獨保留物理模型;它將避免由於外鍵*和*物理存儲在數據庫中的列表而引起的任何更新異常。如果團體成員可以改變(即人們可以隨時間加入或離開團隊),那麼這會更安全。我最近做了一些非常類似的事情,非常快(在SQL Server中使用了xml路徑)。 –