Mysql 表「;产品“;使用预定义的产品,用户可以自定义价格。如何避免数据冗余?

Mysql 表「;产品“;使用预定义的产品,用户可以自定义价格。如何避免数据冗余?,mysql,database,cakephp,Mysql,Database,Cakephp,我已经思考这个问题好几天了,但我仍然找不到一个方法来做我想做的事情 下面是我的数据库目前的设计方式(这正是我被困的地方): 这就是我想要的: 用户可以创建多个价格表。用户可以给价格表起任何他想要的名字。有两种价格表类型:“实验室履行”或“自我履行” 如果用户选择“实验室履行”,他可以导入其中一个预定义实验室的全部或部分产品。(我的意思是:很少有实验室提供预定义的产品列表)。用户只能自定义价格。他不能将定制产品添加到此价格表中 如果用户选择“自我实现”,他可以添加自己的产品,并可以个性化每个字

我已经思考这个问题好几天了,但我仍然找不到一个方法来做我想做的事情

下面是我的数据库目前的设计方式(这正是我被困的地方):

这就是我想要的:

  • 用户可以创建多个价格表。用户可以给价格表起任何他想要的名字。有两种价格表类型:“实验室履行”或“自我履行”
  • 如果用户选择“实验室履行”,他可以导入其中一个预定义实验室的全部或部分产品。(我的意思是:很少有实验室提供预定义的产品列表)。用户只能自定义价格。他不能将定制产品添加到此价格表中
  • 如果用户选择“自我实现”,他可以添加自己的产品,并可以个性化每个字段(名称、成本、价格、维度、维度)
我不知道如何把他们之间的表格联系起来。如果我将预定义产品放在Products表中,并在价格表和产品之间设置多对多关系,则当用户自定义预定义产品时,它的默认价格将被覆盖,这不是我想要的

此外,我希望预定义产品的默认值在数据库中仅为一次。如果100个用户使用预定义的产品,我不希望默认成本在我的数据库中出现100次

请不要犹豫,要求精确,我很难把这个问题弄清楚,我认为它仍然不是完全清楚


提前感谢您的帮助

好的,数据库规范化101。有很多方法可以做到这一点,我需要一天时间来真正优化所有这些,这应该会有帮助:

User

Lab

Product
id        name           cost          dimension   .....
1         a
2         b
3         c
4         d
所以这三张桌子很好。您的所有产品都将列入产品表。这些表中没有外键

PriceSheet
user_id   custom_price   product_id    type
1         1.99           1             lab-fulfillment
0         NULL           2             self-fulfillment
1         5.99           3             lab-fulfillment
因此,用户可以拥有任意数量的价格表,他们只能调整产品的价格。如果您愿意,这实际上可以进一步规范化:

PriceSheet (composite key on id, user_id, FK user_id)
id   user_id
0    0
1    1
2    1

LabPriceSheet (you could add an id, might be better, or you could use a composite key, stricter)
PriceSheet_id       custom_price   lab_product_id
0                   1.99           0
2                   5.99           1

CustomPriceSheet
PriceSheet_id       custom_product_id
1                   0
根据需要使用外键。这使得MySQL限制了自定义的_价格,而不是在PHP中(尽管您仍然需要确保正确的插入!)

现在,要处理谁添加了这些产品:

CustomProduct
id    user_id    product_id    timestamp
0     3          2             ...      

LabProduct
id    lab_id     product_id    timestamp
0     0          1             ...  
1     0          3             ...  
让我们再检查一下:

这就是我想要的:

用户可以创建多个价格表检查用户可以提供价格表 他想叫什么名字都行检查有两种价格表类型:“实验室 实现”,或“自我实现”检查

如果用户选择“实验室履行”,他可以导入其中一个预定义实验室的全部或部分产品。(我的意思是:很少有实验室提供预定义的产品列表)。用户只能自定义价格。他不能将定制产品添加到此价格表中

是的,因为他将创建一个LabPriceSheet,该LabPriceSheet只能添加lab_product_id。自定义价格也存在,它覆盖了product表中的默认价格

如果用户选择“自我实现”,他可以添加自己的产品,并可以个性化每个字段(名称、成本、价格、维度、维度)

是的,他会添加一个产品(您需要检查是否存在类似的产品,否则在product表中返回现有产品的id),然后这也是CustomProduct中的一个条目

我不知道如何把他们之间的表格联系起来。如果我将预定义产品放在Products表中,并在价格表和产品之间设置多对多关系,则当用户自定义预定义产品时,它的默认价格将被覆盖,这不是我想要的

是的,这不会发生:)永远(很少)实现很多rel

此外,我希望预定义产品的默认值仅为 一次在我的数据库里。如果100个用户使用预定义的产品,则I 不希望默认成本在我的数据库中出现100次

当然

让我知道如果你想要MySQL代码,我想你是好的!记住使用InnoDB并正确配置您的MySQL配置

编辑 我想帮你复制粘贴。我喜欢复制和粘贴东西。此外,在布告栏中有一个多余的user_id列,我在前面的编辑中修复了该列

SET GLOBAL innodb_file_per_table = 1;
SET GLOBAL general_log = 'OFF';
SET FOREIGN_KEY_CHECKS=1;
SET GLOBAL character_set_server = utf8mb4;
SET NAMES utf8mb4;
CREATE DATABASE SO; USE SO;
ALTER DATABASE SO CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci;

CREATE TABLE `User` (
  `id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
  `email` VARCHAR(555) NOT NULL,
  `password` VARBINARY(200) NOT NULL,
  `username` VARCHAR(100) NOT NULL,
  `role` INT(2) NOT NULL,
  `active` TINYINT(1) NOT NULL,
  `created` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `modified` DATETIME ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8mb4;

CREATE TABLE `Lab` (
  `id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
  `name` VARCHAR(1000) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8mb4;

CREATE TABLE `Product` (
  `id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
  `name` VARCHAR(1000) NOT NULL,
  `password` VARBINARY(200) NOT NULL,
  `cost` DECIMAL(10, 2) NOT NULL,
  `price` DECIMAL(10, 2) NOT NULL,
  `height` DECIMAL(15, 5) NOT NULL,
  `length` DECIMAL(15, 5) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8mb4;

CREATE TABLE `CustomProduct` (
  `id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
  `user` BIGINT(20) UNSIGNED NOT NULL,
  `product` BIGINT(20) UNSIGNED NOT NULL,
  `created` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  FOREIGN KEY (`user`) REFERENCES `User`(`id`),
  FOREIGN KEY (`product`) REFERENCES `Product`(`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8mb4;

CREATE TABLE `LabProduct` (
  `id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
  `lab` BIGINT(20) UNSIGNED NOT NULL,
  `product` BIGINT(20) UNSIGNED NOT NULL,
  `created` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  FOREIGN KEY (`lab`) REFERENCES `Lab`(`id`),
  FOREIGN KEY (`product`) REFERENCES `Product`(`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8mb4;

CREATE TABLE `PriceSheet` (
  `id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
  `name` VARCHAR(1000) NOT NULL,
  `user` BIGINT(20) UNSIGNED NOT NULL,
  PRIMARY KEY (`id`,`user`),
  FOREIGN KEY (`user`) REFERENCES `User`(`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8mb4;

CREATE TABLE `LabPriceSheet` (
  `id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
  `price_sheet` BIGINT(20) UNSIGNED NOT NULL,
  `lab_product` BIGINT(20) UNSIGNED NOT NULL,
  `custom_price` DECIMAL(10, 2) NOT NULL,
  PRIMARY KEY (`id`),
  FOREIGN KEY (`price_sheet`) REFERENCES `PriceSheet`(`id`),
  FOREIGN KEY (`lab_product`) REFERENCES `LabProduct`(`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8mb4;

CREATE TABLE `CustomPriceSheet` (
  `id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
  `price_sheet` BIGINT(20) UNSIGNED NOT NULL,
  `custom_product` BIGINT(20) UNSIGNED NOT NULL,
  PRIMARY KEY (`id`),
  FOREIGN KEY (`price_sheet`) REFERENCES `PriceSheet`(`id`),
  FOREIGN KEY (`custom_product`) REFERENCES `CustomProduct`(`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8mb4;

嗨,尤金!哇,这是一个地狱般的答案!非常感谢,我正在努力完全理解它是如何工作的。如果我还有任何问题,我会再打给你。