Reputation: 6872
I have the following fields in my table:
id - user_id - display_time - icon_id - background_id - page_name - template_id - sort_id - time
Basically, each user has their own slides that they can create and these are just some settings within it. These are for the custom slides but each user will have 12 or so default slides that are pre-made.
My question is.. for the pre-made slides that all users get, I don't need to define all of those fields. It will already have a background and icon and all of that, that cannot be changed. However it needs to be on this table because the user can still change the sort order and the time.
So... I could define the background and icon for each pre-made slide, but in the future if I did want to change the background of the universal "Dashboard" page then there is no easy way to make the change, since it is already in the database for that background_id.
Sorry if that was really confusing. Does anyone have any suggestions on how to approach this? I hope I have the right idea here.
So this table is good for the custom slides but I need to fit the universal pages that all users get in here so they can define some important variables like how long the slide will show for and the order. Is there an easier way to do this?
Edit:
I need to have the ability to add more than 1 of the same slide in the sort order. So if someone wants slide 1 to show up again and just change the sort order and display time. So they can have many different "instances" of each slide.
Can I take out the slide_id PRIMARY key without it messing anything up? It says it is Unique right now which I think is making this mess up if I try to add another of the same slide.
Thanks!
Upvotes: 1
Views: 284
Reputation: 562731
This is similar to the answer given by @Freeman Latif. Showing the table definitions may make it more clear where the sort and display attributes belong: these attributes belong in the table that associates users to their slide choices.
I'm making some guesses about how you flexible you want these attributes to be. So my apologies if you have different intentions for the attributes than my design supports.
For instance, I'm adding a Templates table so that you can define a default icon & background and then apply that design as a default to the slides. Then if you ever change the default background, you only need to change it in one row in the Templates table instead of many rows in the Slides table. That's part of the benefit of normalization: a fact like the background is only recorded in just one place, so you don't accidentally change it on some rows and not other rows.
CREATE TABLE Templates (
template_id INT PRIMARY KEY,
icon_id INT,
background_id INT
);
CREATE TABLE Slides (
slide_id INT PRIMARY KEY,
template_id INT,
page_name VARCHAR(20),
FOREIGN KEY (template_id) REFERENCES SlideTemplates(template_id)
);
CREATE TABLE SlideCustom (
slide_id INT PRIMARY KEY,
icon_id INT,
background_id INT,
FOREIGN KEY (slide_id) REFERENCES Slides(slide_id)
);
Note that slide_id is both a foreign key referencing Slides, and also the primary key of SlideCustom. So it has a 1:1 relationship to that table.
A given user's slide choices include the choice of slide, whether it is a default slide or a custom slide, and the user's choice for sort order and display time. Therefore multiple users can choose a given slide, but each user can have a different choice for sort and display of that slide.
CREATE TABLE UserSlides (
user_id INT NOT NULL,
slide_id INT NOT NULL,
sort_order INT NOT NULL,
display_tenths_sec INT NOT NULL DEFAULT 10,
PRIMARY KEY (user_id, slide_id),
FOREIGN KEY (user_id) REFERENCES Users(user_id),
FOREIGN KEY (slide_id) REFERENCES Slides(slide_id)
);
Now you can get every slide for a user and the slide's icon and background, whether it's default or custom:
SELECT u.user_id, u.display_tenth_sec,
COALESCE(c.icon_id, t.icon_id) AS icon_id,
COALESCE(c.background_id, t.background_id) AS background_id,
FROM UserSlides u
JOIN Slides s USING (slide_id)
LEFT OUTER JOIN SlideCustom c USING (slide_id)
LEFT OUTER JOIN Templates t USING (template_id)
WHERE u.user_id = 20860
ORDER BY u.sort_order;
Re your comment and additional requirement that a user can use a given slide more than once:
Certainly the sort order is unique for a given user. So you can make (user_id, sort_order) be the primary key, and slide_id is just another non-unique attribute:
CREATE TABLE UserSlides (
user_id INT NOT NULL,
slide_id INT NOT NULL,
sort_order INT NOT NULL,
display_tenths_sec INT NOT NULL DEFAULT 10,
PRIMARY KEY (user_id, sort_order),
FOREIGN KEY (user_id) REFERENCES Users(user_id),
FOREIGN KEY (slide_id) REFERENCES Slides(slide_id)
);
Upvotes: 3
Reputation: 57798
First of all, "id" is a little ambiguous, so I'd rename that to "slide_id".
For the default slides, you could add a "default_slide" column (with a value of 0 for not and 1 indicating "default"). This way you could have your default slides in the same table as the other slides, but you could easily code your application to not allow those slides to be updated. You could accomplish the same thing with a check constraint or trigger, but I'm a believer in keeping business logic in the application (not the database).
Also, you'll want to split-out "user_id" from this table into a bridge table that looks like this:
table: user_slides
user_id int
slide_id int
This way, you only need to define the rows for the default slides once, but many users can have access to them.
Upvotes: 0
Reputation: 1190
You can separate this table into 3 different tables: 1 for the default slides that will never change (this should have 12 rows for the 12 default slides), 1 for the rest of the informations which are dynamic (sort time, time), 1 for the "custom" slides that the user made. The 3 tables should be connected by the slide_id. Then use INNER JOIN and UNION to display the tables together.
Upvotes: 0