2011-01-19 67 views
3

我們有一個計劃表,每個計劃都有很多服務。我們想找一個快速的方式查找不包含重複服務但是作爲組合包含某些服務的計劃組合。生成行組合的最快方法

例如計劃表

id | service_1 | service_2 | ... 
--------------------------------- 
1 | true | true  | ... 
2 | true | false | ... 
3 | false | true  | ... 

例如,含SERVICE_1和service_2有效組合

UPDATE

如果有2個服務,我需要他們兩個,我們將結合高達2行(或計劃),因爲它們可能包含在每個最小1個服務。

id | service_1 | service_2 | id | service_1 | service_2 | 
--------------------------------------------------------- 
1 | true | true  |NULL| NULL | NULL | 
2 | true | false | 3 | false | true | 

UPDATE

目前,它的工作原理是自我留下了積極的修剪或行合本身。該查詢是基於服務數量動態生成的。它創建了有效連接條件的排列,使其不太實際。

當前成本是按計劃數量^服務數量的順序。

我最感興趣的是解決這個問題的其他方法,不一定要改進目前的方式。

+1

請發佈您迄今爲止編寫的代碼。人們通常不喜歡只爲你寫代碼。事實上,這是一個工作描述,而不是一個問題。 – 2011-01-19 01:57:54

+1

沒有足夠的信息。您將在搜索中指定多少項服務,以及允許使用多少計劃來回答查詢? – 2011-01-19 02:11:16

+0

還有什麼可以幫到的? – Moriarty 2011-01-19 02:24:18

回答

1

這似乎是工作確定

設置數據

DROP TABLE IF EXISTS plan; 
CREATE TABLE plan (id int, service1 bool, service2 bool, service3 bool); 
INSERT INTO `plan` (`id`, `service1`, `service2`, `service3`) VALUES (1, 1, 0, 0); 
INSERT INTO `plan` (`id`, `service1`, `service2`, `service3`) VALUES (2, 0, 1, 0); 
INSERT INTO `plan` (`id`, `service1`, `service2`, `service3`) VALUES (3, 1, 1, 1); 
INSERT INTO `plan` (`id`, `service1`, `service2`, `service3`) VALUES (4, 1, 0, 1); 
INSERT INTO `plan` (`id`, `service1`, `service2`, `service3`) VALUES (5, 0, 0, 1); 

查詢

select * 
from plan A 
left join (
    select id, service1, service2, service3 from plan 
    union all 
    select null, null, null, null) B on B.id > A.id or B.id is null 
left join (
    select id, service1, service2, service3 from plan 
    union all 
    select null, null, null, null) C on C.id > B.id or C.id is null 
WHERE (A.service1 + A.service2 + A.service3) 
    AND (A.service1 + ifnull(B.service1,0) + ifnull(C.service1,0)) = 1 
    AND (A.service2 + ifnull(B.service2,0) + ifnull(C.service2,0)) = 1 
    AND (A.service3 + ifnull(B.service3,0) + ifnull(C.service3,0)) = 1 

結果

id | service1 | service2 | service3 | id | service1 | service2 | service3 | id | service1 | service2 | service3 
1 | 1 | 0 | 0 | 2 | 0 | 1 | 0 | 5 | 0 | 0 | 1 
1 | 1 | 0 | 0 | 5 | 0 | 0 | 1 | 2 | 0 | 1 | 0 
2 | 0 | 1 | 0 | 4 | 1 | 0 | 1 | NULL | NULL | NULL | NULL 
2 | 0 | 1 | 0 | NULL | NULL | NULL | NULL | 4 | 1 | 0 | 1 
3 | 1 | 1 | 1 | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL 
1

正如我在評論中提到的,由哪一個規則決定一個「重複」不清楚。然而,從它的聲音,你只是做一個按位與。

With RawData As 
    (
    Select 1 As id, 1 As service_1, 1 As service_2 
    Union All Select 2, 1, 0 
    Union All Select 3, 0, 1 
    ) 
    , BinData As 
    (
    Select A.id, A.service_1, A.service_2 
     , A.service_1 * 2 + A.service_2 As Bin 
    From RawData As A 
    ) 
Select * 
From BinData As F1 
    Left Join BinData As F2 
     On F2.id <> F1.id 
      And F1.Bin & F2.Bin = 0 
Order By F1.id 

但是,您將在此解決方案中注意到,我得到id = 3的行。出於同樣的原因,id = 3是id = 2的「重複」,反過來也是如此。

如果這是不正確的,我們需要更多的清晰度和一些更好的示例數據來說明什麼是和不是「重複」的邊緣情況。

更新

考慮什麼cyberwiki在評論中指出的那樣,如果什麼正在尋求每一個計劃是聯合提供的所有服務恰好一次當另一個計劃,則正在尋求的是一個二進制的恭維會產生全部1。我們可以做的是通過查找,當進行XOR運算,目前的計劃都計劃生產所有的人:

With RawData As 
    (
    Select 1 As id, 1 As service_1, 1 As service_2 
    Union All Select 2, 1, 0 
    Union All Select 3, 0, 1 
    ) 
    , BinData As 
    (
    Select A.id, A.service_1, A.service_2 
     , A.service_1 * 2 + A.service_2 As Bin 
    From RawData As A 
    ) 
Select *, F1.Bin^F2.Bin 
From BinData As F1 
    Left Join BinData As F2 
     On F2.id <> F1.id 
      And F1.Bin^F2.Bin = 3 
Order By F1.id 

再次注意,ID = 3將在結果顯示因爲正如ID = 3是絕配id = 2,反過來也是如此。