What's the proper way to store this data in a MySQL schema?

强颜欢笑 提交于 2019-12-04 03:55:12

Instead of a single row for each movie, use an attribute-value table. Then add an additional field to this that specifies the user, which would be 0 for the original default. So the table looks like:

MovieID UserID  Attribute   Value
1       0       Title       12 Monkeys
1       0       Format      DVD
1       1       Title       Twelve Monkeys

Then a query to get the title would look like:

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'

Some database designers also like to use an AttributeID rather than a string as the attribute name, and a separate table that maps attribute names to IDs.

I suggest there is no 'proper' way. But you might like this...

  • Your Movie table stays as is. (I assume there is an id.)
  • Another table, UserMovie with the same columns except:
    • All the columns except id are NULL
    • It has another column: user NOT NULL
    • PRIMARY KEY(id, user)

When a user modifies something, use INSERT INTO UserMovie .. ON DUPLICATE KEY UPDATE .. to change whatever field(s) he wants to set. Note that IODKU will INSERT a new row if none exists, or UPDATE the existing row (because the user is modifying another column). For example, to override just the "title" for id=$id,

INSERT INTO UserMovie
    (id, title)
    VALUES
    ($id, '$title')
ON DUPLICATE KEY UPDATE
    title = '$title';

When a user wants to see what he has,

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;

The COALESCE quietly pics either u.xxx if NOT NULL, or m.xxx.

This design has the advantage of being very compact. (NULLs take almost no space.)

If a user changes the "title" twice, only the last version is kept.

To "revert" the title:

UPDATE UserMovie SET title = NULL
    WHERE id = $id
      AND user = $user;

(Sure, this could leave a row of all NULLs, but the rest of the code still works.)

My first thought is, Why would you want to do this?

My second thought is to have a customizations table something like

+--------+---------+-------------+------------+
| userid | barcode | column_name | custom_val |
+--------+---------+-------------+------------+

then, when a user queries the system, look up their userid and the column_name in the customizations table to find the alternative display value.

This would allow a user to replace one value in one row. To replace one value in all rows where it exists would be a much more difficult proposition.

A good design is not perfect for all situations. However there is a perfect design for a situation.

Ask yourself again: 1) what the purpose of this design and, 2) how are you going to retrieve the data from the design.

According to your question, if a movie never changes its attributes, a flat one-row table is perfect:

table: movie
id | barcode      | format_id | runtime | disc | year_made | title
---+--------------+-----------+---------+------+-----------+-----------
1  | 025192018626 | 1         | 121     | 1    | 1995      | 12 Monkeys

And you might need a foreign table movie_format

table: movie_format
id | format
---+-------
1  | DVD

Above design is very speedy for search.

Now you want to save any changes, or alternative information, however not sure what they are. In this case, a meta table is more suitable. Meta table is usually perfect if you only need to display according to a primary key (a movie) and not used for a search:

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     | 十二头傻猴子

You can make movie_meta.meta as enum so that you do not need to worry about a new lookup table

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!