-2

在我询问有关编码的更多问题之前,我想首先找出我可以遵循的最佳方法来制作我的数据库。我遇到了一个问题,我应该如何构建它以保持一切最小化,并且由于它的性质,我有很多我必须代表的重复出现的数据。

我设计定制衬衫,并有各种不同类型的衬衫供人们选择,有成人和儿童两种尺寸可供选择。例如,我有适合男士、女士、男孩、女孩和幼儿的圆领衬衫、插肩袖、戒指袖和连帽衫。每件衬衫的价格相同,从幼儿尺码到成人尺码的 1 倍,然后 2 倍、3 倍、4 倍和 5 倍的价格各不相同。然后是每种衬衫的颜色选择各不相同,有些可能有 4 种颜色选择,有些有 32 种。

因此,让我们仅以圆领衬衫为例。Men s-1x, Women s-1x, Boys xs-1x, Girls xs-1x 和 toddlers NB-18months 共有 22 行,将在表格中表示并且价格相同。2X 及以上仅适用于男性和女性,因此增加了 8 行,仅圆领衬衫总共有 30 行。当它进入颜色选项时,有 32 种不同的颜色可供它们使用。如果我要为所有这些尺寸做每一个尺寸,那么仅针对圆领衬衫的总行数将是 960 行,其中主要是高度重复的数据,只需要一个小改动。

我想了想,认为最好把桌子上的这些物品当作储藏室里的实际物品,因为它们真的在储藏室里……你不会只有一盒可以打孔的衬衫侧面的按钮变成任何尺寸的颜色,你必须处理实际的衬衫和将它们放在某个地方的繁琐任务,所以我决定不要试图用一堆外键和索引来变得离谱,除了它只是很乏味,当您可以将其链接到的数据放在第一个表中时,您最终不得不表示同样多但有更多表的表。

如果我们只取其他 3 种衬衫,并仅针对这 4 种衬衫对所有颜色和尺码应用相同的逻辑,那么将有 3,840 行,剩下的其他衬衫我不算在内,你可以说我是在一张表中查看大约 10,000 行数据。这些数据将随着时间的推移而增长,我想知道它可能会变成什么来保持一切井井有条。所以我认为最好的逻辑可能是像在实际零售店中那样将其分解,将部门分为男性、女性、男孩、女孩和婴儿。这样我就有了 5 个单独的表,只有在用户决定“去那个部门”时才会调用它们,所以如果有人想要男士衬衫,他没有 7,000 多行的额外数据,甚至没有适用于他'

这会是更好的设置方法吗?还是将其全部保留为一张巨大的桌子,然后从男性部分的表中查询 php 中的“男士”衬衫,女性和儿童也一样?

我的下一个问题是所有可能可用的颜色选项,正如我之前所说的,有些衬衫只有 4 种,有些则多达 32 种,所以其中一些数据足以单独形成一个表格,所以我真的可以为每种衬衫单独准备一张桌子。我将在 php 中使用查询来填充表格中的项目,因此我不必在 html 和 javascript 中编写太多代码。这样我就可以将它设置为SELECT ALL * table WHERE type=men它会占用所有男士衬衫并自动填充每件衬衫的编码。这样,当我在表格中添加和取走东西时,它会自动更新。我已经对我将如何做到这一点有了一个想法,但我只能想到这么远,因为我还没有决定一个好的方法来设置表格,这是我必须将它构建成的来电。

例如,如果我将每件衬衫的所有颜色选项都放在同一张表上,而不是将其分解并链接到其他表来表示它们的外键。那将是两种完全不同的调用方式,所以我被困在这个问题上,真的不知道该去哪里。有什么建议么?

4

3 回答 3

4

通常零售组织是按 SKU(库存单位)。部门和颜色是服装的属性,而不是您出于会计或库存目的识别服装的方式。

CREATE TABLE Skus (
  sku BIGINT UNSIGNED PRIMARY KEY,
  description TEXT,
  department VARCHAR(10) NOT NULL,
  color VARCHAR(10) NOT NULL,
  qty_in_stock INT UNSIGNED NOT NULL DEFAULT 0,
  unit_price NUMERIC(9,2) NOT NULL,
  FOREIGN KEY (department) REFERENCES Departments(department),
  FOREIGN KEY (color) REFERENCES Colors(color)
);

这比分成五个表要好,因为:

  • 您可以快速获得所有股票总价值的总和。
  • 您可以轻松切换给定 SKU 的部门。
  • 当某人购买几件衣服时,他们的订单项目引用一个表而不是五个不同的表(这对于关系数据库是无效的)。

如果类似的实体存储在一个表中,还有许多其他任务示例会更容易。

于 2012-12-21T21:35:31.757 回答
2

我知道您不想将其分成单独的表格,但我认为采用多表格路线是最好的。不过,我觉得没有你想的那么糟糕。我的建议如下。显然,您想更改字段的名称,但这是一种快速表示:

衬衫

  - id (primary key)
  - description
  - men (Y/N)
  - women (Y/N)
  - boy (Y/N)
  - girl (Y/N)
  - toddlers (Y/N)

尺寸

  - id (primary key)
  - shirt_id (foreign key)
  - Size

颜色

  - id (primary key)
  - shirt_id (foreign key)
  - Color

价格

  - id (primary key)
  - shirt_id (foreign key)
  - size_id (foreign key)
  - price

有了这三个表,您就不必将所有 10,000 行存储在一个表中并进行维护,但数据仍然存在。将数据分开放置在适当的位置可以避免复制不必要的信息。

想拉所有男士衬衫?

SELECT * FROM shirts WHERE men = '1'

老实说,你真的应该至少有 5 或 6 张桌子。一/二包含尺寸和颜色的标签(一张表包含所有标签,或者每个表一张),另外 4 个包含实际数据。这将使您的数据在所有内容中保持统一(例如:Bluevs blue)。你知道他们说什么,给猫剥皮的方法不止一种。

于 2012-12-21T21:36:02.997 回答
1

您需要考虑一个称为“规范化”的数据库术语。规范化意味着一切都在数据库中,不应该列出两次,而是根据需要重用。人们最常犯的错误是不问或不考虑未来会发生什么,他们建立了一个几乎没有规范化、对大型数据类型消耗大量内存、没有做种子、完全不灵活和以后改变要付出很大的代价,因为它是在没有考虑未来的情况下做出的。

标准化有很多级别,但最一致的事情是考虑一个简单的例子,我可以给你解释一些可以在以后应用于更大的事情的简单概念。这是假设您可以访问 SQL 管理工作室、SSMS,但是如果您使用的是 MYSQL 或 Oracle,原理仍然非常相似,评论部分将显示我的意思。如果您有 SSMS,则可以自行运行此示例,只需将其粘贴并按 F5。如果您不只是查看评论部分,尽管这些概念在实践中比试图想象它们的含义更好。

Declare @Everything table (PersonID int, OrderID int, PersonName varchar(8), OrderName varchar(8) );

insert into @Everything values (1, 1, 'Brett', 'Hat'),(1, 2, 'Brett', 'Shirt'),(1, 3, 'Brett', 'Shoes'),(2,1,'John','Shirt'),(2,2,'John','Shoes');

-- very basic normalization level in that I did not even ATTEMPT to seperate entities into different tables for reuse.
-- I just insert EVERYTHING as I get in one place.  This is great for just getting off the ground or testing things.
-- but in the future you won't be able to change this easily as everything is here and if there is a lot of data it is hard 
-- to move it.  When you insert if you keep adding more and more and more columns it will get slower as it requires memory 
-- for the rows and the columns
Select Top 10 * from @Everything

declare @Person table ( PersonID int identity, PersonName varchar(8));

insert into @Person values ('Brett'),('John');

declare @Orders table ( OrderID int identity, PersonID int, OrderName varchar(8));

insert into @Orders values (1, 'Hat'),(1,'Shirt'),(1, 'Shoes'),(2,'Shirt'),(2, 'Shoes');

-- I now have tables storing two logic things in two logical places.  If I want to relate them I can use the TSQL language
-- to do so.  I am now using less memory for storage of the individual tables and if one or another becomes too large I can 
-- deal with them isolated.  I also have a seeding record (an ever increasing number) that I could use as a primary key to 
-- relate row position and for faster indexing
Select *
from @Person p 
    join @Orders o on p.PersonID = o.PersonID

declare @TypeOfOrder table ( OrderTypeID int identity, OrderType varchar(8));

insert into @TypeOfOrder values ('Hat'),('Shirt'),('Shoes')

declare @OrderBridge table ( OrderID int identity, PersonID int, OrderType int)

insert into @OrderBridge values (1, 1),(1,2),(1,3),(2,2),(2,3);


-- Wow I have a lot more columns but my ability to expand is now pretty flexible I could add even MORE products to the bridge table
-- or other tables I have not even thought of yet.  Now that I have a bridge table I have to list a product type ONLY once ever and 
-- then when someone orders it again I just label the bridge to relate a person to an order, hence the name bridge as it on it's own
-- serves nothing but relating two different things to each other.  This method takes more time to set up but in the end you need 
-- less rows of your database overall as you are REUSING data efficiently and effectively.
Select Top 10 *
from @Person p 
    join @OrderBridge o on p.PersonID = o.PersonID
    join @TypeOfOrder t on o.OrderType = t.OrderTypeID
于 2012-12-21T21:38:18.680 回答