日期:2014-02-02  浏览次数:20365 次

集合之间的关系绿色c hinaip ower. comaFrwyXt

为了介绍我在本文中讨论的问题,首先我们来回顾一下集合论中表示集合之间关系的几个概念。我使用这些概念来为本文所讨论的问题定义条件。我用大写字母指定集合名称,用编号的小写字母指定集合成员,用里面包含集合成员的花括号指定集合本身。绿色c hinaip ower. comaFrwyXt

集合论描述了集合之间可以存在的某些关系:绿色c hinaip ower. comaFrwyXt

集合 U 等于集合 V,条件是:U 的所有成员都存在于 V 中,并且 V 的所有成员都存在于 U 中 - 例如,U = {u1, u2, u3},V = {u1, u2, u3}。 绿色c hinaip ower. comaFrwyXt

如果 U 的所有成员都存在于 V 中,则 U 是 V 的子集。当 U 等于 V 时,U 是 V 的子集,V 也是 U 的子集。绿色c hinaip ower. comaFrwyXt

当 U 是 V 的子集,但 V 不是 U 的子集时,U 是 V 的真子集 - 例如,U = {u1, u2, u3},V = {u1, u2, u3, u4}。绿色c hinaip ower. comaFrwyXt

我在本文中讨论的任务涉及到确定与另一个项组有某种关系的项组,也就是集合。我们先来看一个提出问题的示例。绿色c hinaip ower. comaFrwyXt

Orders OrderDetails 方案绿色c hinaip ower. comaFrwyXt

我使用的方案涉及到作为示例的 Orders 表和 OrderDetails 表,您可以运行 清单 1显示的脚本在 tempdb 中创建并填充这两个表。这些表只包括了与本文讨论内容相关的列 - 即,Orders 中的 orderid 列和 OrderDetails 中的 orderid 和 productid 列。Orders 表中的每个订单在 OrderDetails 表中可能不存在相关行;或存在一个或多个相关行,每一行都包含不同的产品。就其本质来说,每个定单都是实体的一个实例,但在本文中,我所指的定单是属于定单的一组详细信息。绿色c hinaip ower. comaFrwyXt

应用程序用户输入一组代表新定单的产品,您的代码将它们存储在 #ProdList 临时表中:绿色c hinaip ower. comaFrwyXt

CREATE TABLE #ProdList(productid int NOT NULL PRIMARY KEY)



INSERT INTO #ProdList VALUES(2)



INSERT INTO #ProdList VALUES(3)



INSERT INTO #ProdList VALUES(4)



您从市场营销部门接受了几个任务,要求您确定新定单和现有定单之间的不同关系。这些关系对于市场营销部门可能很重要,营销部门会据此确定采购模式,考虑某些产品组的折扣,等等。绿色c hinaip ower. comaFrwyXt

任务 1P O 的子集。您的第一个任务是确定包含 #ProdList 中的所有产品的定单。用集合术语来说,如果 O 代表构成定单的定单详细信息的集合,P 代表 #ProdList 中的产品的集合,您就要查找满足“P 是 O 的子集”这一条件的定单。您的查询应该返回定单 A 和 B。绿色c hinaip ower. comaFrwyXt

下面的查询为您提供了该任务的解决方案:绿色c hinaip ower. comaFrwyXt

SELECT orderid



FROM OrderDetails



WHERE productid IN(SELECT productid FROM #ProdList)



GROUP BY orderid



HAVING COUNT(*) = (SELECT COUNT(*) FROM #ProdList)



此代码查询 OrderDetails 表,筛选出只包含存在于 #ProdList 中的产品的行。该查询按 orderid 对结果进行分组,然后筛选产品数与 #ProdList 表中的产品数相同的组。该查询只返回包含 #ProdList 中的所有产品的定单。绿色c hinaip ower. comaFrwyXt

任务 2P 等于 O您的第二个任务是确定包含 #ProdList 中的所有产品但不包含其他产品的定单。用集合术语来说,您要查找满足“P 等于 O”这一条件的订单。在前面的查询中,WHERE 子句去除了那些包含 #ProdList 中不存在的产品的行,所以该查询未考虑那些行。但这一次,您需要考虑所有行。要解决此问题,您可以先编写一个返回 OrderDetails 中的所有行的查询,向结果追加到一个名为 inlist 的列中;对于 #ProdList 中存在的产品,该列的取值为 1,对于不包含的产品,该列的取值为 -1:绿色c hinaip ower. comaFrwyXt

SELECT *,



CASE



WHEN productid IN(SELECT



productid FROM #ProdList)



THEN 1



ELSE -1



END AS inlist



FROM OrderDetails



图 1显示了此查询的结果。绿色c hinaip ower. coma