2011-11-28 180 views
4

我還沒有找到解決方案的運氣,部分原因是我不確定如何最好地解釋問題!希望我在這裏清楚,但如果不是,請隨時索取更多信息。將列表與其他多個列表進行比較

在頂層: 在我們的數據庫中,每個客戶可以有多個服務。服務分別分配給客戶。但是,爲了報告目的,我們需要將「羣組」服務納入常見服務組合的「套餐」中。

我有一個包含包定義的數據庫 - 一個名爲packageServices的表,簡單地列出每個包ID與關聯的ServiceID。因此,我可以檢索每個包的服務列表。

從同一個數據庫中,我可以檢索特定客戶的ServiceID列表。

我試圖完成的是比較爲該客戶檢索的ServiceIDs列表,並查看該組合是否與任何定義的pacakges(即ServiceIDs的組合)匹配,如果是這樣,則報告該客戶的哪個軟件包具有。

我比較努力地知道從哪裏開始!我想我需要首先爲每個包創建一些serviceID列表(而不是我當前的KeyValuePairs(在字典中)),然後遍歷這些包並將這些服務列表與列表進行比較客戶有哪些服務?

這裏使用可能不是最合適的數據類型 - 在許多情況下,我指的是一個「邏輯」列表,而不是一個C#列出對象 - 我可以任意使用的數據類型是適當:)

任何幫助非常感激!

編輯 - 有人建議我在SQL中整理這些信息,而不是在我的C#應用​​程序中。這似乎是一個好主意,下面的答案之一使我接近。然而,有一些「商業規則」可以確定一個軟件包是否是對一個較低的軟件包或一個軟件包的「升級」,這是一件非常複雜的事情。

我越努力使這項工作越多,我認爲我咬掉的東西越多,我就可以咀嚼!我是,試着正確設計,以便將來對服務或軟件包所做的任何更改都能輕鬆處理 - 這些更改不太可能,但可能。但是,從目前爲止所看到的選項中進行硬編碼將更加容易!

編輯2 - 我一直在努力解決這個問題,並建議我爲每個包分配一個「權重」和「組」。這些組在那裏確保客戶只能從每個組中獲得一個包,並且權重在那裏以確保只返回「最高」級包。將這與@MarceloCantos的查詢結合使用,意味着我應該只能返回每個組的「最高」權重包 - 這看起來可能符合應用程序的要求!

感謝迄今爲止幫助過的所有人 - 我驚訝地發現響應的響應速度以及響應的質量。我會給出一個去看看我如何繼續。

+1

我們在討論服務,包裹,每個服務的典型包裹等等時,我們討論的是什麼樣的大小數字? – AakashM

+0

@AakashM - 好點。服務和軟件包總是相對較小 - 目前有7種服務可以分爲8種軟件包 - 這種情況將會增長,但不會顯着。到目前爲止,每個軟件包的最大服務數量是6個。客戶數量將增長到數千個。然而,這些'計算'只需要每月進行一次。 – JimmE

+0

這是一次「一次性」的工作來確定每個客戶擁有哪些軟件包,或者您需要在有人訪問該網站時做到這一點?正如Dave在下面提出的那樣,將數據存儲在數據庫中會更有意義 - 今天就完成一次,然後確保它已更新,而且您再也無需再次處理它。 –

回答

1

您可以爲客戶計數服務,然後對於具有相同服務數量的每個包計算與客戶服務匹配的服務。只有完全匹配纔會產生相同的計數。

您可以在一個查詢中做到這一點,雖然是一個不調皮之一:

SELECT CustomerID, PackageID 
    FROM (SELECT CustomerID, COUNT(*) AS qty 
      FROM customerServices 
     GROUP BY CustomerID 
     ) cs 
    JOIN (SELECT PackageID, COUNT(*) AS qty 
      FROM packageServices 
     GROUP BY PackageID 
     ) ps ON cs.qty = ps.qty 
WHERE (SELECT COUNT(*) 
      FROM customerServices cs2 
      JOIN packageServices ps2 ON cs2.ServiceID = ps2.ServiceID 
     WHERE cs2.CustomerID = cs.CustomerID 
      AND ps2.PackageID = ps.PackageID 
     ) = ps.qty 

編輯:也許我誤解了這個問題。如果你想找到包含客戶的服務的子集包,你可以這樣做,而不是:

... 
     ) ps ON cs.qty >= ps.qty -- Change the test 
WHERE (SELECT COUNT(*) 
      FROM customerServices cs2 
      JOIN packageServices ps2 ON cs2.ServiceID = ps2.ServiceID 
     WHERE cs2.CustomerID = cs.CustomerID 
      AND ps2.PackageID = ps.PackageID 
     ) = ps.qty 

編輯2:我改變了第二種情況中的邏輯漏洞的事實,如果兩個集合的交集與較小集合的大小相同,則較小集合是較大集合的子集。

+0

他必須爲每個包含<=服務數量的包作爲客戶端 – Bond

+0

@Marcelo坎多斯 - 非常感謝 - 儘管我解釋得很糟,但我認爲你已經理解了這個問題!你說得很對,客戶可以擁有額外的服務,而不是軟件包的一部分。讓我詳細考慮您的解決方案並報告回來,但是在SQL中做這件事很有意義。 – JimmE

+1

@JimmE:NP。順便說一句,我改變了邏輯。我意識到在測試子集時,您仍然可以使用set-counting方法 - 從而避免了double-NOT-EXISTS混亂。 –

3

我建議您不要嘗試計算客戶訂閱的包裹(訂閱可能不是正確的詞,但你知道我的意思)。我建議你保留單獨的記錄,指出客戶在數據庫中訂閱的包裹。每次客戶添加新服務時,都會使用一條消息指出發生添加服務的事件,並通過使用隨新產品添加完成的任何包更新該客戶的包來處理該事件。

+0

非常感謝 - 在某種程度上,我同意。我不想就這種方式對業務原因進行太詳細的描述,因爲我不想讓你們都感到厭倦 - 但這似乎與我認爲我們需要在飛行中計算這一點的原因有關。 – JimmE

+0

無聊與否,商業原因可能是題外話題。我很難想象商業需求會決定你不能做一些反規範化,但是你當然比我更瞭解你的領域。沒有這個,你可能想讓數據庫像marcelo所建議的那樣處理這些集合的搗碎,因爲rdbms是爲此而構建的。另一種手工製作sql的替代方法是使用帶有linq提供程序的orm並在linq中表示查詢。儘管如此,我擔心你會在這種方法的規模上遇到問題。也許你不關心規模,所以它可能工作。 –

+0

我還建議,商業規則是口授技術解決方案的觀念可能意味着您正在對業務真正需要的一些假設做出一些假設,這些假設可能有效也可能不正確,或者業務正在向您推動技術解決方案,這是您如果可以的話應該抵制。可能值得重新審視這些要求,看看您是否可以決定他們是否真的沒有表達業務意圖。 –

相關問題