我在MySQL数据库中有一个movie
。 movie
包含永不改变的数据属性,例如:
它是表格中的一行。
但是我想让我的用户对这些信息进行完全自定义,以防万一根据它们不正确,或者他们只是想以某种方式修改数据的显示方式。我不在乎为什么,我只是想让我的用户选择他们想要的东西。
假设用户#1想要将他们的标题更改为“12 Monkeys(Shelf 1)”,这就是他们所有的变化。
让我们说用户#2想要将DVD改为数字拷贝。
让我们说用户#3想要将他们的标题更改为“十二只猴子”,因为它是替代标题。
等
我的问题是,如何在不修改原始数据的情况下,只将 存储一个字段更改为该用户名?在一个单独的相同表中,除了一个字段外,所有字段都是完全相同的数据?或者我可以在某处存储一个单独的更改(例如标题)并返回其余的movie
数据?
设计这个的正确方法是什么,特别是如果我有1000个用户主要在一两个字段上进行自定义数据修改?
答案 0 :(得分:13)
使用属性值表而不是每部电影的单行。然后为此添加一个指定用户的附加字段,原始默认值为0
。所以表格如下:
MovieID UserID Attribute Value
1 0 Title 12 Monkeys
1 0 Format DVD
1 1 Title Twelve Monkeys
然后获取标题的查询将如下所示:
SELECT MovieID, IFNULL(my.Value, default.Value) AS title
FROM movies AS default
LEFT JOIN movies AS my ON default.MovieID = my.MovieID AND my.Attribute = 'Title' AND my.userID = @user
WHERE default.UserID = 0 AND default.Attribute = 'Title'
一些数据库设计人员也喜欢使用AttributeID
而不是字符串作为属性名称,以及使用单独的表将属性名称映射到ID。
答案 1 :(得分:7)
我建议没有适当的'办法。但你可能会喜欢这个......
Movie
表保持不变。 (我假设有一个id
。)UserMovie
具有相同的列,但以下情况除外:
id
以外的所有列均为NULL
user NOT NULL
PRIMARY KEY(id, user)
当用户修改某些内容时,请使用INSERT INTO UserMovie .. ON DUPLICATE KEY UPDATE ..
更改他想要设置的任何字段。请注意,如果不存在,IODKU将INSERT
新行,或者UPDATE
现有行(因为用户正在修改另一列)。例如,要仅覆盖"标题"对于id = $ id,
INSERT INTO UserMovie
(id, title)
VALUES
($id, '$title')
ON DUPLICATE KEY UPDATE
title = '$title';
当用户想要查看他拥有的内容时,
SELECT coalesce(u.title, m.title) AS title,
coalesce(u.format, m.format) AS format,
coalesce...
FROM Movie AS m
LEFT JOIN UserMovie AS u
ON u.id = m.id
AND u.user = $user
WHERE m.id = $id;
如果COALESCE
或u.xxx
,NOT NULL
会m.xxx
静静地拍照。
这种设计具有非常紧凑的优点。 (NULLs
几乎没有空间。)
如果用户更改"标题"两次,只保留最后一个版本。
To" revert"标题:
UPDATE UserMovie SET title = NULL
WHERE id = $id
AND user = $user;
(当然,这可能会留下所有NULLs
的一行,但其余的代码仍然有用。)
答案 2 :(得分:3)
我的第一个想法是,你为什么要这样做?
我的第二个想法是让customizations
表格像
+--------+---------+-------------+------------+
| userid | barcode | column_name | custom_val |
+--------+---------+-------------+------------+
然后,当用户查询系统时,在customizations
表中查找其用户标识和column_name以查找替代显示值。
这将允许用户替换一行中的一个值。要在存在它的所有行中替换一个值将是一个更加困难的命题。
答案 3 :(得分:2)
好的设计并非适用于所有情况。然而,对于某种情况,有一个完美的设计。
再问自己:1)这个设计的目的是什么,2)你将如何从设计中检索数据。
根据你的问题,如果电影永远不会改变它的属性,那么平面的单行表是完美的:
table: movie
id | barcode | format_id | runtime | disc | year_made | title
---+--------------+-----------+---------+------+-----------+-----------
1 | 025192018626 | 1 | 121 | 1 | 1995 | 12 Monkeys
你可能需要一个外表table_format
table: movie_format
id | format
---+-------
1 | DVD
以上设计非常快速搜索。
现在您要保存所有更改或替代信息,但不确定它们是什么。在这种情况下,元表更合适。如果您只需要根据主键(电影)进行显示而不用于搜索,则元表通常是完美的:
table: movie_meta
id | movie_id | user_id | created | meta | info
---+----------+---------+---------------------+-----------+---------
1 | 1 | 123 | 2016-01-28 11:22:33 | format_id | 2
2 | 1 | 456 | 2016-01-28 11:55:33 | disc | 3
5 | 1 | 666 | 2016-07-14 12:58:55 | title | 十二头傻猴子
您可以将movie_meta.meta设为enum,这样您就不必担心新的查找表