确定谁拥有MySQL中的可转移项目

时间:2015-07-21 19:42:34

标签: mysql sql

我正在制作一款游戏,用户可以使用虚拟货币购买虚拟物品,并将这些物品交给其他用户。我们需要能够跟踪物品的历史(谁买了它,谁被赋予了它等)和当前的所有者。我正在努力解决一些桌面设计问题。

我的想法是(稍微简化表格设计并省略空间的约束/键/等):

TABLE order
id                 INT NOT NULL AUTO_INCREMENT,
buyer_id           INT NOT NULL,
paid               INT UNSIGNED NOT NULL,
owned_item_id     INT NOT NULL,
------------------------------------------------------
TABLE owned_item
id                 INT NOT NULL AUTO_INCREMENT,
store_product_id   INT NOT NULL,
owner_id           INT NOT NULL,
------------------------------------------------------
TABLE gift
id                 INT NOT NULL,
giver_id           INT NOT NULL,
receiver_id        INT NOT NULL,
owned_item_id      INT NOT NULL,

根据想法,购买商品时,会为该商品创建 order owned_item 。如果该项目有资格,则会在 gift 表格中创建一个新条目,并更新owner_id字段。

这种方法可以很容易地确定当前拥有给定项目的人。 然而,它具有冗余数据,并为数据完整性问题留下了空间。如果'owner_id'字段设置不正确,我们最终可能会得到A购买并赠送给B的项目的记录,但现在却被C莫名其妙地拥有。

这样的结构应该如何规范化?我考虑过删除 owned_item 表:

TABLE order
id                 INT NOT NULL AUTO_INCREMENT,
buyer_id           INT NOT NULL,
paid               INT UNSIGNED NOT NULL,
product_id         INT NOT NULL,
------------------------------------------------------
TABLE gift
id                 INT NOT NULL,
giver_id           INT NOT NULL,
receiver_id        INT NOT NULL,
order_id           INT NOT NULL,

我不喜欢这个解决方案,因为查找某个人拥有的所有项目都会变得非常复杂(找到每个礼物记录X,其中收件人是A,并且没有以后的礼品记录存在于同一订单中,与find结合使用每个订单记录Y,其中买方是A并且该订单不存在礼品记录)但如果这是正确的解决方案,那么我将做。

1 个答案:

答案 0 :(得分:0)

对于您正在寻找的事情,这样的事情将是一个很好的3nf架构。

实体和交易保持通用,以便简化所有实体/交易关系。

-- An Entity is a person or business, as a party in a transaction
CREATE TABLE entity (
id                  INT NOT NULL AUTO_INCREMENT,
entity_type         ENUM('store', 'person') NOT NULL
name                VARCHAR NOT NULL
);

-- Unique item types - items are each an instance of an item-type
-- e.g. the item "Steve's broom" may be an item of type "broom"
CREATE TABLE item_type (
id                  INT NOT NULL AUTO_INCREMENT,
name                VARCHAR NOT NULL
);

-- Non-unique item, instance of an item-type owned by an entity
CREATE TABLE item (
id                  INT NOT NULL AUTO_INCREMENT,
-- optionally include owner_id as a quick-reference to the current owner of the item
owner_id            INT NULL REFERENCES entity (id), 
-- FK to unique item types, e.g. "broom"
item_type_id        INT NOT NULL REFERENCES item_type (id), 
-- possible description, e.g. "Steve's broom"
description         VARCHAR NOT NULL 
);

-- A transaction is a sale, gift, or other method of transferrence
-- of an item between entities.  Transaction is a bad name, because
-- it's a reserved word.  That's why it's encased in ticks.
-- You'd probably be better off choosing a different generic name
CREATE TABLE `transaction` (
id
-- transaction_type can be NULL in cases of origination with entity
transaction_type    ENUM('sale', 'gift') NULL,
-- NULL in cases of origination with an entity
from_entity_id      INT NULL REFERENCES entity (id), 
to_entity_id        INT NOT NULL REFERENCES entity (id),
-- amount can be 0 in cases of gifts
amount              DECIMAL(9,2) UNSIGNED NOT NULL DEFAULT 0
);

A"礼物"事务的数量为0(如果你想让它可以为空,则为NULL)。

"起源"事务(例如,某事已经发现或被发现)将没有transaction_type和0 amount。

要知道项目的当前所有者是谁,请使用一个视图来检索最后一个" to_entity_id"对于交易表中的该项目,例如:

SELECT 
    e.name
FROM entity AS e
INNER JOIN `transaction` AS t ON e.id = t.to_entity_id
INNER JOIN
    (SELECT MAX(id) AS id
    FROM `transaction`
    WHERE item_id = 5) AS tx ON tx.id = t.id

或者,您也可以将owner_id存储在项目表中(请参阅上面的架构中的注释)。这将是一个多余的,并且需要在每个事务上更新该表,但是会节省大量昂贵的查询以了解谁拥有什么。