如何在数据库中创建和/或关系?

如何在数据库中创建和/或关系?

问题描述:

我有优惠券表。优惠券只适用于某些物品或适用于整个类别的物品。如何在数据库中创建和/或关系?

例如:$ 5优惠券比萨饼12" (1L百事可乐OR薯条)

最好我能想出是使含有coupon_id和有点CouponMenuItems表如IsOr和IsAnd。它不起作用,因为我在这个例子中有2组项目,第二个项目是2项目之间的OR关系

任何想法,我怎么能做到这一点逻辑实施尽可能简单吗?

任何帮助或提示表示赞赏!

感谢,

Teebot

+0

相信与否这不是一项家庭作业:)这是一个在线列表的当地餐馆,您可以从网上订购。老板让我把这个逻辑添加到他的网站上。 – teebot 2008-10-23 12:15:00

通常,您可以通过使用Disjunctive Normal Form来简化这种事情。

你将你的逻辑标准化为一系列的不连贯 - “或子句”。每个分离符都被设置为“和子句”。

所以你的规则成为下面的长分隔符。

  • 比萨百事可乐

OR

  • 比萨薯条

(你总是可以做到这一点,顺便说一句,与任何逻辑问题米是有些事情可能会非常复杂。好消息是没有营销人员会试图对你产生困惑的逻辑。此外,从任何旧形式到分离正态形式的重写都是一种简单的代数。)

这个,你会注意到,总是两层深:总是一个顶层的不连续的列表(任何其中一个可能是真实的)和一个较低级别的连词列表(所有这些都必须是真实的)。

因此,您有一个“条件”表,其中包含id和产品名称等列。这定义了订单项和产品之间的简单比较。

你有一个Conjuncts(“中级和子句”)表,其中包含像连接ID和条件ID这样的列。连词与条件之间的连接将产生连词的所有条件。如果所有这些条件都是真的,那么合并是真实的。

拥有一个Disjuncts(“*或子句”)表,其中包含像disjunct Id和conjunct ID这样的列。如果其中一个断言是真实的,则断言是真实的。

分离符,连词和条件之间的连接会产生一组需要测试的条件。

+0

不错的。我自己也是为了类似的问题做了这个。它似乎比起一个更“关系”的方法来说更复杂,但实际上它很自然地适用于“优惠券”(在我的情况下为特价)场景。 – Draemon 2008-10-24 01:50:15

你可以把单个项目作为自己的组(1件),只是实现纯逻辑券映射到组。

您需要将所有关系组合在一起,定义它们如何分组,然后将优惠券分配给这些关系。从本质上讲,你需要数据库实体来表示你的榜样括号,但你需要一个或多个外层的括号:

(比萨12" AND(1L百事可乐或薯条))

Coupon 
    CouponId 
    Name 
    ... 

Item 
    ItemId 
    Name 
    ... 

Group 
    GroupId 

GroupMembership 
    GroupMembershipId 
    GroupId 
    ItemId 

ItemAssociation 
    ItemAssociationId 
    Item1Id 
    Item2Id 
    IsOr : bit -- (default 0 means and) 

GroupAssociation 
    GroupAssociationId 
    Group1Id 
    Group2Id 
    IsOr : bit -- (default 0 means and) 

集思广益这个结构之后它看起来像是一个可以用节点父/子关系层次结构解决的问题。ItemAssociation/GroupAssociation表气味对我来说,我认为一个可以处理的通用关联表可能是可取的,因此您可以编写通用代码来处理所有关系(尽管你会失去参照完整性,除非你也将项目和组概括为一个实体)。

注意:同时命名实体组可能会产生问题。 :)

一种可能的方法来考虑。假设您创建了以下类别:

+----------+  1 +---------------+ * 
| Coupon |<#>------>| <<interface>> |<--------------+ 
+----------+   | CouponItem |    | 
| +value |   +---------------+    | 
+----------+   | +cost()  |    | 
         +---------------+    | 
          /|\      | 
           |      | 
      +--------------------------------+   | 
      |     |    |   | 
     LeafCouponItem AndCouponItem OrCouponItem | 
          <#>   <#>  | 
           |    |   | 
           +-------------+---------+ 

和:

class Coupon { 
    Money value; 
    CouponItem item; 
} 

interface CouponItem { 
    Money cost(); 
} 

class AndCouponItem implements CouponItem { 
    List<CouponItem> items; 
    Money cost() { 
     Money cost = new Money(0); 
     for (CouponItem item : items) { 
      cost = cost.add(item.cost()); 
     } 
     return cost; 
    } 
} 

class OrCouponItem implements CouponItem { 
    List<CouponItem> items; 
    Money cost() { 
     Money max = new Money(0); 
     for (CouponItem item : items) { 
      max = Money.max(max, item.cost); 
     } 
     return max; 
    } 
} 

class LeafCouponItem implements CouponItem { 
    Money cost; 
    Money cost() { 
     return cost; 
    } 
} 

并映射到2个表:

COUPON   COUPON_ITEM 
------   ----------- 
ID    ID 
VALUE    COUPON_ID  (FK to COUPON.ID) 
        DISCRIMINATOR (AND, OR, or LEAF) 
        COUPON_ITEM_ID (FK to COUPON_ITEM.ID) 
        DESCRIPTION 
        COST    

因此,对于你的例子中,你将有:

> SELECT * FROM COUPON 

ID    100 
VALUE   5 

And

> SELECT * FROM COUPON_ITEM 

ID  COUPON_ID DISCRIMINATOR COUPON_ITEM_ID DESCRIPTION COST 
200  100   AND    NULL    NULL   NULL 
201  100   LEAF    200    PIZZA   10 
202  100   OR    200    NULL   NULL 
203  100   LEAF    202    PEPSI   2 
204  100   LEAF    202    FRIES   3 

这种单表方法高度非规范化,有些人宁愿为每个CouponItem实现分开表。

大多数ORM框架将能够照顾这样一个类的域的存在。

我的建议:

Table 
    primary key 
= = = = = 
COUPONS 
    coupon_id 

PRODUCT_GROUPS 
    group_id 

ITEM_LIST 
    item_id 

ITEM_GROUP_ASSOC 
    item_id, group_id 

COUPON_GROUP_ASSOC 
    coupon_id, group_id 

COUPON_ITEM_ASSOC 
    coupon_id, item_id 

COUPON_ITEM_ASSOC表中,有一个字段指示优惠券可以有多少项申请一次,与一些特殊的值,表示“无限”。