如何在数据库中创建和/或关系?
我有优惠券表。优惠券只适用于某些物品或适用于整个类别的物品。如何在数据库中创建和/或关系?
例如:$ 5优惠券比萨饼12" 和(1L百事可乐OR薯条)
最好我能想出是使含有coupon_id和有点CouponMenuItems表如IsOr和IsAnd。它不起作用,因为我在这个例子中有2组项目,第二个项目是2项目之间的OR关系
任何想法,我怎么能做到这一点逻辑实施尽可能简单吗?
任何帮助或提示表示赞赏!
感谢,
Teebot
通常,您可以通过使用Disjunctive Normal Form来简化这种事情。
你将你的逻辑标准化为一系列的不连贯 - “或子句”。每个分离符都被设置为“和子句”。
所以你的规则成为下面的长分隔符。
- 比萨和百事可乐
OR
- 比萨和薯条
(你总是可以做到这一点,顺便说一句,与任何逻辑问题米是有些事情可能会非常复杂。好消息是没有营销人员会试图对你产生困惑的逻辑。此外,从任何旧形式到分离正态形式的重写都是一种简单的代数。)
这个,你会注意到,总是两层深:总是一个顶层的不连续的列表(任何其中一个可能是真实的)和一个较低级别的连词列表(所有这些都必须是真实的)。
因此,您有一个“条件”表,其中包含id和产品名称等列。这定义了订单项和产品之间的简单比较。
你有一个Conjuncts(“中级和子句”)表,其中包含像连接ID和条件ID这样的列。连词与条件之间的连接将产生连词的所有条件。如果所有这些条件都是真的,那么合并是真实的。
拥有一个Disjuncts(“*或子句”)表,其中包含像disjunct Id和conjunct ID这样的列。如果其中一个断言是真实的,则断言是真实的。
分离符,连词和条件之间的连接会产生一组需要测试的条件。
不错的。我自己也是为了类似的问题做了这个。它似乎比起一个更“关系”的方法来说更复杂,但实际上它很自然地适用于“优惠券”(在我的情况下为特价)场景。 – 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
表中,有一个字段指示优惠券可以有多少项申请一次,与一些特殊的值,表示“无限”。
相信与否这不是一项家庭作业:)这是一个在线列表的当地餐馆,您可以从网上订购。老板让我把这个逻辑添加到他的网站上。 – teebot 2008-10-23 12:15:00