2011-11-28 140 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

我还建议,商业规则是口授技术解决方案的观念可能意味着您正在对业务真正需要的一些假设做出一些假设,这些假设可能有效也可能不正确,或者业务正在向您推动技术解决方案,这是您如果可以的话应该抵制。可能值得重新审视这些要求,看看您是否可以决定他们是否真的没有表达业务意图。 –

相关问题