Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 5 years ago.
Improve this question
I'm new to PHP and MySQL. For my project I want to make a site for lyrics. How to design the database and the relationships?
Here is what I have so far:
Artist
Artist_id
Artist_name
Artist_bio
Artist_thumb
Albums
Album_id
Artist_id
Genre_id
Album_title
Release_year
Genre
genre_id
genre_name
Tracks
track_id
track_title
album_id
Please let me know if I'm wrong.
Be consistent with whether your
table names are singular or plural. My preference is singular, because then when you're doing multi-table queries, you can refer to a column simply as "track.id", rather than "tracks.id".
Ensure all your table and field
names are spelled correctly (i.e.
"genre"); this is something that's a
pain to change later.
Finally, I wouldn't advise prefixing the column names with their parent table's name. It's just redundant.
artist
id
name
bio
thumb
album
id
artist_id
genre_id
title
release_year
genre
id
name
track
id
title
album_id
I strongly recommend WWWSQLDesigner to design your database. Guideline that brianreavis had mentioned are really worthy of listening. Always use correct spelling, use consistent grammar, capitalization and underlining (_). Also you may consider adding multiple genres using a relationship table.
album_genre ( id int, album int, genre int )
For album or artist pictures, I recommend you to save them to a folder with their related id's. Observe,
id = 14
artist = 42
title = Mask And Mirror
year = 1994
thumbnail: /thumbnails/album-14.jpg
Your design looks pretty good. Some additional tables that you may want to add:
Playlist
PlaylistTrack
PlayedTrack
You could add additional fields to the Track table. For example:
trackSortOrder
trackYear
trackGenre
trackLength
userRating
bitRate
author
copyright
numberOfPlays
lastPlayedDate
dateAdded
Important questions you should be asking yourself while designing
What is my requirement!?! In your case, what all information should my lyrics website have? Should it tell me who actually wrote the song? When was it written? Who all have sung that song etc etc. So first thing is you have to define the scope! Your Entities and database design will depend on that!
What are my entities?
what are the relationships between my main entities?
Your design might be pretty descent and might work perfectly for your requirement but depending on how much of complexity you are willing to handle (requirement scope!), you might have to take care of things like:
Artist and Album actually have many to many relationship. Many artists might work on same album and of course a single artist will have multiple albums. Your current design will cope up with this but do you want genreId, title, release_year being duplicated when multiple artists work together for an album? There is a trade off involved here between creating 1 more table and storing duplicate values. Your current design might be perfect for what you are doing, but just wanted to make sure that you have given it a thought
In real world, multiple artists collaborate to write a song. Mostly songs are written by someone else and sung by someone else. You need to define what Artist means to you. Is it the person who sung the song? Is it someone who wrote the song? Are both artists? If I search for the writer of the song who has not sung a single song, should it return results?
I dont see a table where you are storing lyrics! But I guess you already know that :)
I can see a few more things which might cause you problems later on, but as I said, I don't know what is the scope of your requirement! :)
You're conflating multiple different types of objects in a few places -- for instance, it looks like you're trying to create a single rating table which applies to albums, artists, and tracks. Consider carefully whether it may be easier to have three separate tables for the three different types of ratings.
Same thing goes for comment. Additionally, on that table, your current structure (having a single comment_id on an album, artist, or track) would appear to limit each type of object to having a single comment, which doesn't make sense.
For genre, type, and thumb, consider inlining those tables into the parent object. Would it ever make sense to have a single thumb row which is shared between multiple artists, for instance, or would it be easier to just have each artist have a thumb path stored directly in it?
Finally, for all of the relationships you've drawn out, you need to define the cardinality of the relationship. For each one, define which table is referring to the other, and "how many" rows in one table can exist for each row in the other one. For instance, the relationship between album and track is a one-to-many relationship, as each album contains multiple tracks, but each track belongs to one album. Use a notation such as "crow's foot notation" to denote this information.
How about having a separate table for album and a common table which defines the relationship between all the other tables?
Related
I have a MySQL database set up with a list of all my movies, which I imported from a MS Access database. One field contains the possible values for the genre of the movie, movies can have more than one genre, so I need a data type which supports this feature. In access I could link one table 'genre' to the field 'genre' in my table 'movies', so I could choose none, one ore multiple genres per movie. When I switched to MySQL I used the SET data type to define all the possible values. So far everything is running perfectly.
I am now trying to set up a table in html/php to show the mysql table. I want the table to be able to sort on: title, genre, quality, rating, etc. But for the sorting on genre, I would need the possible values from the set data type. I don't know if it is possible to get the values with some php command/code, but after I lurked around on the web for a while, I didn't see many applications where they use the SET data type for obvious negative reasons.
So I started looking into the Foreign Key possibility. The problem I have here is that -for as far as I know- the key can only contain one possible value, which puts me right back at the start of my problem. I do like the idea of a foreign key, because it would make it way easier for me to add a new genre to the list.
Is there a possibility I am overlooking? Is it possible to either get the values from the SET type to php or to use a foreign key with multiple possibilities for one record?
I know I can also put every genre in my php script manually, but I'd like to have it all on one place. So that if I add a movie with a genre I haven't defined yet, I can just update it at one place and everything else adapts to it.
Dagon is absolutely right here - you have an issue with the structure of the tables in your back end. You are wanting to model a many to many relationship when at the moment with your current back end the best you can do is a one to many relationship.
To review:
You have individual films that can have many genres
And you have individual genres that are related to many films
Relational databases actually don't model many to many relationships with one relationship they use recursion of the one to many relationship and create two joins.
To model a many to many relationship you need three tables
A film table (which I think you already have)
A genre table (which I think you already have)
A junction table which as Dagon suggests will consist of two fields film id and genre id.
You then set up two separate one to many relationships. One from the film table to the junction table and one from the genre table to the junction table.
Now if you want to know all the genres a film is in you simply filter the junction table on the relevant film id and if you want to know all the films with a certain genre you filter the junction table on the genre id.
Set up lookups to relate your genre ids to textual descriptions and bang you are free to change the textual description as much as you want and the great thing if you've done it right it will upgrade every single value in your forms.
This is an absolute fundamental concept of the algebra of sets behind the design of SQL and relational database design.
So I'm a visual designer type guy who has learned a respectable amount of PHP and a little SQL.
I am putting together a personal multimedia portfolio site. I'm using CI and loving it. The problem is I don't know squat about DB design and I keep rewriting (and breaking) my tables. Here is what I need.
I have a table to store the projects:
I want to do fulltext searcheson titles and descriptions so I think this needs to be MyISAM
PROJECTS
id
name (admin-only human readable)
title (headline for visitors to read)
description
date (the date the project was finished)
posted (timestamp when the project was posted)
Then I need tags:
I think I've figured this out. from researching.
TAGS
tag_id
tag_name
PROJECT_TAGS
project_id (foreign key PROJECTS TABLE)
tag_id (foreign key TAGS TABLE)
Here is the problem I have FOUR media types; Photo Albums, Flash Apps, Print Pieces, and Website Designs. no project can be of two types because (with one exception) they all require different logic to be displayed in the view. I am not sure whether to put the media type in the project table and join directly to the types table or use an intermediate table to define the relationships like the tags. I also thinking about parent-types/sub-types i.e.; Blogs, Projects - Flash, Projects - Web. I would really appreciate some direction.
Also maybe some help on how to efficiently query for the projects with the given solution.
The first think to address is your database engine, MyISAM. The database engine is how MySQL stores the data. For more information regarding MyISAM you can view: http://dev.mysql.com/doc/refman/5.0/en/myisam-storage-engine.html. If you want to have referential integrity (which is recommended), you want your database engine to be InnoDB (http://dev.mysql.com/doc/refman/5.0/en/innodb-storage-engine.html). InnoDB allows you to create foreign keys and enforce that foreign key relationship (I found out the hard way the MyISAM does not). MyISAM is the default engine for MySQL databases. If you are using phpMyAdmin (which is a highly recommended tool for MySQL and PHP development), you can easily change the engine type of the database (See: http://www.electrictoolbox.com/mysql-change-table-storage-engine/).
With that said, searches or queries can be done in both MyISAM and InnoDB database engines. You can also index the columns to make search queries (SELECT statements) faster, but the trade off will be that INSERT statements will take longer. If you database is not huge (i.e. millions of records), you shouldn't see a noticeable difference though.
In terms of your design, there are several things to address. The first thing to understand is an entity relationship diagram or an ERD. This is a diagram of your tables and their corresponding relationships.
There are several types of relationships that can exist: a one-to-one relationship, a one-to-many relationship, a many-to-many relationship, and a hierarchical or recursive relationship . A many-to-many relationship is the most complicated and cannot be produced directly within the database and must be resolved with an intermittent table (I will explain further with an example).
A one-to-one relationship is straightforward. An example of this is if you have an employee table with a list of all employees and a salary table with a list of all salaries. One employee can only have one salary and one salary can only belong to one employee.
With that being said, another element to add to the mix is cardinality. Cardinality refers to whether or not the relationship may exist or must exist. In the previous example of an employee, there has to be a relationship between the salary and the employee (or else the employee may not be paid). This the relationship is read as, an employee must have one and only one salary and a salary may or may not have one and only one employee (as a salary can exist without belonging to an employee).
The phrases "one and only one" refers to it being a one-to-one relationship. The phrases "must" and "may or may not" referring to a relationship requiring to exist or not being required. This translates into the design as my foreign key of salary id in the employee table cannot be null and in the salary table there is no foreign key referencing the employee.
EMPLOYEE
id PRIMARY KEY
name VARCHAR(100)
salary_id NOT NULL UNIQUE
SALARY
id PRIMARY KEY
amount INTEGER NOT NULL
The one-to-many relationship is defined as the potential of having more than one. For example, relating to your portfolio, a client may have one or more projects. Thus the foreign key field in the projects table client_id cannot be unique as it may be repeated.
The many-to-many relationship is defined where more than one can both ways. For example, as you have correctly shown, projects may have one or more tags and tags may assigned to one or more projects. Thus, you need the PROJECT_TAGS table to resolve that many-to-many.
In regards to addressing your question directly, you will want to create a separate media type table and if any potential exists whatsoever where a project is can be associated to multiple types, you would want to have an intermittent table and could add a field to the project_media_type table called primary_type which would allow you to distinguish the project type as primarily that media type although it could fall under other categories if you were to filter by category.
This brings me to recursive relationships. Because you have the potential to have a recursive relationship or media_types you will want to add a field called parent_id. You would add a foreign key index to parent_id referencing the id of the media_type table. It must allow nulls as all of your top level parent media_types will have a null value for parent_id. Thus to select all parent media_types you could use:
SELECT * FROM media_type WHERE parent_id IS NULL
Then, to get the children you loop through each of the parents and could use the following query:
SELECT * FROM media_type WHERE parent_id = {$media_type_row->id}
This would need to be in a recursive function so you loop until there are no more children. An example of this using PHP related to hierarchical categories can be viewed at recursive function category database.
I hope this helps and know it's a lot but essentially, I tried to highlight a whole semester of database design and modeling. If you need any more information, I can attach an example ERD as well.
Another posibble idea is to add columns to projects table that would satisfy all media types needs and then while editting data you will use only certain columns needed for given media type.
That would be more database efficient (less joins).
If your media types are not very different in columns you need I would choose that aproach.
If they differ a lot, I would choose #cosmicsafari recommendation.
Why don't you take whats common to all and put that in a table & have the specific stuff in tables themelves, that way you can search through all the titles & descriptions in one.
Basic Table
- ID int
- Name varchar()
- Title varchar()
etc
Blogs
-ID int (just an auto_increment key)
-basicID int (this matches the id of the item in the basic table)
etc
Have one for each media type. That way you can do a search on all the descriptions & titles at the one time and load the appropriate data when the person clicked through the link from a search page. (I assume thats the sort of functionality you mean when you say you want to be able to let people search.)
I am building a classified ads website, similar to craigslist.
The site is divided in to several sections; i.e. Forums, For Sale, Services Offered, etc.
Under each Section there are several [categories], i.e.Forums[pets], Forums[Books], For Sale[barter], Services[Barter], etc. (Notice that some categories are only uniquely identified by their section, such as in the case with barter and barter from two sections "For Sale" and "Services".)
Users will post to the categories from post links within each section. Users can upload photos and select certain amenities for their products, if applicable. A forum post will not need an amenity attribute whereas a Vehicle Ad might. Amenities include: auto transmission for vehicle ads, or furnished for housing rentals.
I am trying to figure the best logical setup for the database schema.
Currently I have this type of logical structure for basic input/query:
SECTIONS TABLE- section_id, section
CATEGORIES TABLE- cat-id, category, section_id(foreign key)
AMENITIES TABLE- amen_id, amenity
PHOTOS TABLE- photos-id, file
POST TABLE- post_id, category, timestamp, description
SECTION_POST TABLE- section_id, post_id
POST_AMENITY TABLE- post_id, amenity_id
POST_PHOTO TABLE- post_id, photo_id
I made the [SECTION_POST] my main many-to-many because the category in the [POST] must be related to the section. I related CATEGORY to SECTION in the categories table, which looks to me like a M-to-M with the addition of category attribute. Is this ok?
Also, do you have any other suggestions as to how i should be thinking on this schema? I think the problem I am having is mostly related to ignorance not lack of organizational skills. Maybe one of you can educate me or refer me to a decent link that tackles my general problem.
Your design is fairly standard. Here's a couple of comments, and some things to consider:
For your keys where you have an implied dependent relationship
(SECTION_POST for example) many ORM libraries have issues with
dependent relationships and the resultant concatenated keys. There's
also the issue of key allocation. For both of those reasons, many
people will instead give that table its own independent key (which
can conveniently be made AUTO_INCREMENT) and move the original PK to
foreign keys.
In terms of SECTION/CATEGORY, only you can say how important of a concept/entity SECTION is, however the obvious questions would
be, how is a SECTION in any way different from a CATEGORY. You
could have the same structure, with even more flexibility by
having only CATEGORY with a self referencing "PARENT_CATEGORY_ID"
column. This would allow you to define a tree structure of
categories, while at the same time, it's simple to get the top
level categories using IS NULL on the PARENT_CATEGORY_ID.
I'm not clear on how you plan to relate photos to a POST, but it would be nice from a design standpoint to support a M-M
relationship so that you can have multiple photos for a single
post.
Otherwise, you seem to have a good handle on relational design basics. I do a lot of database design, and prefer to use a commercial erd design tool, but there are some free options like Mysql workbench (assuming you're designing for mysql) that can help you visualize your design, and insure that all the SQL DDL is correct. It's also nice to have documentation for the development phase of your project.
I am working on a little project where a user submits an article to MySQL, and then PHP send the post to the screen. So far so good.
Now i want to extend it to a "two level" post system, where people can comment on the articles.
The case is, i dont know how to do that.
The table i use for storing articles:
TABLE: posts
id user date avatar signature post
Should i make a new row named comments in the posts table, or should i place the comments in a seperate table? one for articles, one for comments?
All help is much appreciated.
Depends on how you use it on your website. You have to ask: "are my articles and comments essentially the same concept?" If yes, then use one table, if no, use two. On most websites articles work differently, can be categorized, editted etc., and usually need a different fields which would clutter the comments table... so in that case two tables are more reasonable. But if you conclude that on your website articles and comments are generally the same (but try to think future proof: wouldn't you need to add some article functionality in 2 months?) then you can think of articles also as of comments and have one table for them.
If you decide to merge things to one table, and you realize that you need another column to distinguish type of the post, and that some columns remain unused for some types, it is a clear warning signal you should have two tables!
This is a little subjective, but I would just set up a parent/child relationship on your posts table, make a parent_id column that is a foreign key for the id column in the same table. for extra credit, you can make it a nested set relationship which will allow you to pull the parent and all the children in one query
Let's say I have 10 books, each book has assigned some categories (ex. :php, programming, cooking, cookies etc).
After storing this data in a DB I want to search the books that match some categories, and also output the matched categories for each pair of books.
What would be the best approach for a fast and easy to code search:
1) Make a column with all categories for each book, the book rows would be unique (categs separated by comma in each row ) -> denormalisation from 1NF
2) Make a column with only 1 category in each row and multiple rows per book
I think it is easier for other queries if I store the categories 1 by 1 (method 2), but harder for that specific type of search. Is this correct?
I am using PHP and MySQL.
PPS : I know multi relational design, I prefer not joining every time the tables. I'm using different connection for some tables but that's not the problem. I'm asking what's the best approach for a db design for this type of search: a user type cooking, cookies, potatoes and I want to output pairs of books that have 1,2 more or all matched categs. I'm looking for a fast query, or php matching technique for this thing... Tell me your pint of view. Hope I'm understood
Use method 2 -- multiple rows per book, storing one category per row. It's the only way to make searching for a given category easy.
This design avoids repeating groups within a column, so it's good for First Normal Form.
But it's not just an academic exercise, it's a practical design that is good for all sorts of things. See my answer to Is storing a comma separated list in a database column really that bad?
What you want to do is have one table for books, one table for categories, and one table for connecting books and categories. Something like this:
books
book_id | title | etc
categories
category_id | title | etc
book_categories
book_id | category_id
This is called a many-to-many relationship. You should probably google it to learn more.
This relationship is a Many-To-Many (a book can have multiple categories and a category can be used in several books).
Then we have the following:
Got it?
=]
I would recommend approach number 2. This is because approach 1 requires a full text search of the category column.
You may have some success by splitting it up into two tables: One table has one line per book and a unique id (call the table books), and the other has one line per book per category and references the book id from the first table (call the table bookcategories). Then if you only need book data you use table books, where if you need categories you join both tables.