假设我有两个表,数据不应该通过使用我的应用程序(即域表)来改变,例如汽车模型和颜色一辆车。
models
表列出了不同类型的汽车模型。
colors
表列出了汽车可以进入的不同颜色类型。
现在,它可能不会立即显现,但两者之间存在关系。 颜色可能仅适用于特定型号,或者更有可能是同一品牌的多个型号。 模型当然没有特定颜色,但它确实附带了我想要存储在数据库中的颜色选择或选择。
因此,它们之间存在多对多关系,这表明我应该将该关系的详细信息存储在连接表中。所以,如果你原谅我自己的符号,它看起来像这样:
Volvo V70 <-> Pearl White
Volvo V70 <-> Emerald Green
Volvo V70 <-> Night Black
Volvo V70 <-> Salmon Pink
Volvo V70 <-> Ocean Blue
Volvo V70 <-> Raspberry Red
Volvo V60 <-> Pearl White
Volvo V60 <-> Emerald Green
Volvo V60 <-> Night Black
Volvo V60 <-> Salmon Pink
Volvo V60 <-> Ocean Blue
Volvo V60 <-> Raspberry Red
...
这是很多重复的文字。如果我能做的话会更容易
[Volvo V70, V60, S60, S40] <-> [Pearl White, Emerald Green, Night Black, Salmon Pink, Ocean Blue, Raspberry Red]
然后转到下一个车型和一组颜色。
是否有可以以任何方式简化此过程的常规联接表的任何选项?
答案 0 :(得分:2)
如果模型不共享颜色组,那么设计将是一个表:
model [model] comes in color [color]
如果模型共享颜色组,则有两个表:
model [model] comes in the colors of group [group]
group [group] has color [color]
这些表与投影连接到第一个表:
SELECT model, color FROM model_group NATURAL JOIN group_color
如果模型除了组或代替组之外可以具有特殊的可用和/或不可用的颜色,则具有异常表。表的组现在是默认颜色(如果有):
model [model] has default color group [group]
group [group] has color [color]
model [model] is exceptionally available in color [color]
model [model] is exceptionally unavailable in color [color]
然后,异常表分别与JOIN-plus-PROJECT / SELECT UNIONed和MINUSed / EXCEPTed一起表示第一个表:
SELECT group, color FROM model_default NATURAL JOIN group_colour
EXCEPT SELECT * FROM model_unavailable
UNION SELECT * FROM model_available
“冗余”不是关于多个地方出现的值。它是关于应用程序的多行描述相同的事情。
每个表(和查询表达式)都有一个关联的填充(命名)空白语句模板(又名谓词)。构成真实语句的行会进入表中。如果你有两个独立的谓词,那么你需要两个表。相关值包含在每一行的行中。
关于应用程序的重做行,请参阅this。 (并在我的其他答案中搜索表格的“声明”或“标准”。)规范化有所帮助,因为它取代了其行以“... AND ...”形式表达事物的表格,其他表格表示“... “分开。请参阅this和this。
如果您共享组并且仅使用单个双列表作为模型和颜色,则其谓词为:
FOR SOME group
model [model] comes in the colors of group [group]
AND group [group] has color [color]
因此,第二个项目符号从该谓词中删除了一个“AND”,即“多值依赖项”的来源。否则,如果更改模型的组或组的颜色,则必须同时更改多行。 (重点是减少冗余的错误和复杂性,而不是节省空间。)
如果您不想重复字符串以实现(依赖)原因(以更多连接为代价占用空间或操作速度),则添加名称ID和字符串的表并按id列和值替换旧名称列和值。 (这不是规范化,为了依赖于实现的数据优化权衡,这会使您的模式复杂化。并且您应该演示这是必需的并且有效。)
答案 1 :(得分:1)
当建模多对多关系时,正如Kleskowy在评论中所述,每个关系(模型&lt; - &gt;颜色)在连接表中需要一个条目。
您可以通过以下方式重现您的示例:
CREATE TABLE car_model(car_model_id serial NOT NULL PRIMARY KEY, model_name text NOT NULL);
CREATE TABLE car_color(car_color_id serial NOT NULL PRIMARY KEY, color_name text NOT NULL);
CREATE TABLE join_model_color(
car_model_id int NOT NULL REFERENCES car_model(car_model_id),
car_color_id int NOT NULL REFERENCES car_color(car_color_id),
CONSTRAINT model_color_unique_entries UNIQUE(car_model_id, car_color_id)
);
然后插入您的数据:
INSERT INTO car_model(model_name) SELECT 'Volvo V70' UNION SELECT 'Volvo V60';
INSERT INTO car_color(color_name) SELECT 'Pearl White' UNION SELECT 'Emerald Green' UNION SELECT 'Night Black' UNION SELECT 'Salmon Pink' UNION SELECT 'Ocean Blue' UNION SELECT 'Raspberry Red';
INSERT INTO join_model_color SELECT car_model_id, car_color_id FROM car_model, car_color WHERE model_name = 'Volvo V70' AND color_name IN ('Pearl White', 'Emerald Green', 'Night Black', 'Salmon Pink', 'Ocean Blue', 'Raspberry Red');
INSERT INTO join_model_color SELECT car_model_id, car_color_id FROM car_model, car_color WHERE model_name = 'Volvo V60' AND color_name IN ('Pearl White', 'Emerald Green', 'Night Black', 'Salmon Pink', 'Ocean Blue', 'Raspberry Red');
然后您可以查询您的数据,例如:
SELECT color_name FROM car_model NATURAL INNER JOIN join_model_color NATURAL INNER JOIN car_color WHERE model_name = 'Volvo V70';
SELECT model_name FROM car_model NATURAL INNER JOIN join_model_color NATURAL INNER JOIN car_color WHERE color_name = 'Emerald Green';