2008-10-22 51 views
4

我有優惠券表。優惠券只適用於某些物品或適用於整個類別的物品。如何在數據庫中創建和/或關係?

例如:$ 5優惠券比薩餅12" (1L百事可樂OR薯條)

最好我能想出是使含有coupon_id和有點CouponMenuItems表如IsOr和IsAnd。它不起作用,因爲我在這個例子中有2組項目,第二個項目是2項目之間的OR關係

任何想法,我怎麼能做到這一點邏輯實施儘可能簡單嗎?

任何幫助或提示表示讚賞!

感謝,

Teebot

+0

相信與否這不是一項家庭作業:)這是一個在線列表的當地餐館,您可以從網上訂購。老闆讓我把這個邏輯添加到他的網站上。 – teebot 2008-10-23 12:15:00

回答

5

通常,您可以通過使用Disjunctive Normal Form來簡化這種事情。

你將你的邏輯標準化爲一系列的不連貫 - 「或子句」。每個分離符都被設置爲「和子句」。

所以你的規則成爲下面的長分隔符。

  • 比薩百事可樂

OR

  • 比薩薯條

(你總是可以做到這一點,順便說一句,與任何邏輯問題米是有些事情可能會非常複雜。好消息是沒有營銷人員會試圖對你產生困惑的邏輯。此外,從任何舊形式到分離正態形式的重寫都是一種簡單的代數。)

這個,你會注意到,總是兩層深:總是一個頂層的不連續的列表(任何其中一個可能是真實的)和一個較低級別的連詞列表(所有這些都必須是真實的)。

因此,您有一個「條件」表,其中包含id和產品名稱等列。這定義了訂單項和產品之間的簡單比較。

你有一個Conjuncts(「中級和子句」)表,其中包含像連接ID和條件ID這樣的列。連詞與條件之間的連接將產生連詞的所有條件。如果所有這些條件都是真的,那麼合併是真實的。

擁有一個Disjuncts(「頂級或子句」)表,其中包含像disjunct Id和conjunct ID這樣的列。如果其中一個斷言是真實的,則斷言是真實的。

分離符,連詞和條件之間的連接會產生一組需要測試的條件。

+0

不錯的。我自己也是爲了類似的問題做了這個。它似乎比起一個更「關係」的方法來說更復雜,但實際上它很自然地適用於「優惠券」(在我的情況下爲特價)場景。 – Draemon 2008-10-24 01:50:15

0

你可以把單個項目作爲自己的組(1件),只是實現純邏輯券映射到組。

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表氣味對我來說,我認爲一個可以處理的通用關聯表可能是可取的,因此您可以編寫通用代碼來處理所有關係(儘管你會失去參照完整性,除非你也將項目和組概括爲一個實體)。

注意:同時命名實體組可能會產生問題。 :)

2

一種可能的方法來考慮。假設您創建了以下類別:

+----------+  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框架將能夠照顧這樣一個類的域的存在。

0

我的建議:

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表中,有一個字段指示優惠券可以有多少項申請一次,與一些特殊的值,表示「無限」。

相關問題