I'm designing a database that contains a list of recipes and their ingredients and now i'm in the processing of linking the individual ingredients to their respective recipes. However, i'm having trouble deciding on the best course of action on how to populate the associative entity table.
I have my 3 tables,
CREATE TABLE Ingredient
(
ingredientID int PRIMARY KEY AUTO_INCREMENT,
ING VARCHAR(100)
);
CREATE TABLE Recipe
(
recipeID int PRIMARY KEY AUTO_INCREMENT,
recipeTitle VARCHAR(200),
prepText VARCHAR(10000),
cuisineType VARCHAR(100)
);
CREATE TABLE recipeIng
(
recipeID int,
ingredientID int,
PRIMARY KEY (recipeID, ingredientID)
);
The Ingredient table is populated from an XML file containing 200+ individual ingredients, which each auto assigned a different ID starting at 1.
The Recipe table is populated by another XML file, containing the recipe title, preparation method and cuisine type.
The recipeIng table is what i'm having trouble with, I assume it will have to be populated by hand. i.e manually matching all the ingredients to their recipes. Like this:
INSERT INTO recipeIng
VALUES(1, 1);
INSERT INTO recipeIng
VALUES(1, 2);
INSERT INTO recipeIng
VALUES(1,3);
INSERT INTO recipeIng
VALUES(1, 4);
With '1' being the id of the first recipe and '1', '2' etc being the individual ingredient ID.
However i'm unsure if this is the best approach for the populating the table and any advice would be helpful.
Note: When combined with the in-use method of populating this query works fine.
SELECT r.recipeTitle
FROM Recipe r
INNER JOIN recipeIng e ON e.recipeID=r.recipeID
INNER JOIN Ingredient i ON i.ingredientID = e.ingredientID
WHERE 'brown sugar' IN (i.ING);
By viewing your last questions, I think this approach is at least better than having a comma-separated list of ids in one of the tables. Having a list of comma-separated values would f.e. limit you in the number of connections, depending on the configuration you have for the field storing the list of values.
The way, you showed here, is the way I design mn-relations in relational databases, too. This is also what you'd get using tools like MySQL Designer, so I think it's the best way to store a many-to-many relation.
I haven't really found much documentation around this excepted by this article, which is linked at the Wikipedia page for many-to-many relations: http://www.tomjewett.com/dbdesign/dbdesign.php?page=manymany.php
I am going through this exact situation with my website, but I'm dealing with testimonials instead of recipes. The only thing I have come up with so far that may help you is to do tons of inserts at once. For example, if most of your recipes call for flour, then you could a select insert statement that would insert 'flour' into recipeIng for multiple recipeIDs.
Good luck!
Related
How can i insert multiple values into one row?
My query
insert into table_RekamMedis values ('RM001', '1999-05-01', 'D01', 'Dr Zurmaini', 'S11', 'Tropicana', 'B01', 'Sulfa', '3dd1');
i cant insert two values into one row. is there another way to do it?
I'm ignorant of the human language you use, so this is a guess.
You have two entities in your system. One is dokter, the other is script (prescription). Your requirement is to store zero or more scripts for each dokter. That is, the relationship between your entities is one-to-many.
In a relational database management system (SQL system) you do that with two tables, one per entity. Your dokter table will contain a unique identifier for each doctor, and the doctor's descriptive attributes.
CREATE TABLE dokter(
dokter_id BIGINT AUTO_INCREMENT PRIMARY KEY NOT NULL,
nama VARCHAR (100),
kode VARCHAR(10),
/* others ... */
);
And you'll have a second table for script
CREATE TABLE script (
script_id BIGINT AUTO_INCREMENT PRIMARY KEY NOT NULL,
dokter_id BIGINT NOT NULL,
kode VARCHAR(10),
nama VARCHAR(100),
dosis VARCHAR(100),
/* others ... */
);
Then, when a doctor writes two prescriptions, you insert one row in dokter and two rows in script. You make the relationship between script and dokter by putting the correct dokter_id into each script row.
Then you can retrieve this information with a query like this:
SELECT dokter.dokter_id, dokter.nama, dokter.kode,
script.script_id, script.kode, script.nama, script.dosis
FROM dokter
LEFT JOIN script ON dokter.dokter_id = script.dokter_id
Study up on entity-relationship data design. It's worth your time to learn and will enhance your career immeasurably.
You can't store multiple values in a single field but there are various options to achieve what you're looking for.
If you know that a given field can only have a set number of values then it might make sense to simply create multiple columns to hold these values. In your case, perhaps Nama obat only ever has 2 different values so you could break out that column into two columns: Nama obat primary and Nama obat secondary.
But if a given field could have any amount of values, then it would likely make sense to create a table to hold those values so that it looks something like:
NoRM
NamaObat
RM001
Sulfa
RM001
Anymiem
RM001
ABC
RM002
XYZ
And then you can combine that with your original table with a simple join:
SELECT * FROM table_RekamMedis JOIN table_NamaObat ON table_RekamMedis.NoRM = table_NamaObat.NoRM
The above takes care of storing the data. If you then want to query the data such that the results are presented in the way you laid out in your question, you could combine the multiple NamaObat fields into a single field using GROUP_CONCAT which could look something like:
SELECT GROUP_CONCAT(NamaObat SEPARATOR '\n')
...
GROUP BY NoRM
Suppose I wanted to have a table of users for people who collected various rare video games. Further suppose I made a model for a list of video games that can be created and saved by those users. How would I save the list in the database.
For example, my thoughts are there would be a cell in the user table called game_list which is a comma separated list of game('s). The games being a separate table with static game data and statistics which the users can pick from to create their rare game list.
Is this the best way? BTW, I am using rails, in case of specific solutions. I know this question is rather general, but I have a hard time phrasing the question to google and this site to get the answer I am looking for. I'm quite new to web development (SQL and HTML5 parts mostly), but not programming (been programming for a long time).
Thank you!
This is a many-to-many relationship. One usually models this with a table for user information, a table for game information, and a table for each user-game relation:
create table user(
user_id int primary key,
user_name varchar(255));
create table game(
game_id int primary key,
game_name varchar(255));
create table user_game(
user_id int not null references user(user_id),
game_id int not null references video(video_id));
insert into user values (1, "ed"), (2, "bob");
insert into game values (1, "pacman"), (2, "poker");
insert into user_game values (1, 1), (1, 2), (2, 2);
select user_name, game_name
from user
natural join user_game
natural join game;
http://sqlfiddle.com/#!2/6b637/1
A thing you could do is make a form, so the user can choose which games they wanna store. Then you take the games the user have selected and make a array.
Foreach game in the array you do a query to the table in your database which contains the game data, and you get the id and make a array. Then you use var game_list = serialize($array) in php (http://php.net/manual/en/function.serialize.php), for example and update the user table with the variable you got from serialize().
If you then wanna get the data and make it to a array again you should use var game_list = unserialize($row).
hello i'm trying to make two databases linked for a book review system i'm creating
for example i have a table for books and i also have another table for genres.
The books table will store all the different books and will have a foreign key of the genre it belongs to using a genre_id key or something.
When i do a query for genres i want it to display how many books are in that genre eg 2 books in the fantasy genre.
for that i would need a records column? but how do i have that auto incrementing/deleting when new records are added or deleted?
EDIT:
Wow thanks for all the help so quickly, so i understand i don't need a seperate table for records but say i wanted it to work with this
function all_get() {
$this->load->database();
$sql = 'SELECT * FROM books;';
$query = $this->db->query($sql);
$data = $query->result();
$this->response($data, 200);
}
how would i do the query to show the records each genre has instead of all the seperate books showing individually?
EDIT: I may have misunderstood, initially I thought these are really two separate questions - one on creating an auto incrementing primary key and another on how to show the number of books in each genre.
Counts
On showing the number of books in each genre as well as the name of the genre, I think you're looking for something like this:
SELECT g.genreName, count(*) from books b
JOIN genres g on g.ID = b.genreID
GROUP BY g.genreName
SQL Fiddle: http://sqlfiddle.com/#!2/a3c45e/2
Auto incrementing
As others have already commented, you don't need a separate records table, but in case you still need help with auto incrementing primary keys, here's the most basic example from W3 schools:
CREATE TABLE Persons
(
ID int NOT NULL AUTO_INCREMENT,
LastName varchar(255) NOT NULL,
FirstName varchar(255),
Address varchar(255),
City varchar(255),
PRIMARY KEY (ID)
)
You don't need a records column. You can query how many books are related to each genre:
SELECT count(*) FROM Book WHERE genre_id = :genreId;
BTW before you start you might rethink your entity relations. Is Genre <-> Book really 1:n?
I need to make a table 'Movies' which will have columns:
ID Title Description Category etc
And another one called 'Movie_Categories' containing, for example
ID Category
1 Action
2 Adventure
3 Triller
but since category in table Movies will have multiple choices what is the correct way to do this?
should i use comma-separated values like someone said in this post Multiple values in column in MySQL or is there a better way?
This is a many-to-many relationship.
You need a join table to make it right, such as :
CREATE TABLE film_category (
category_id int,
film_id int,
PRIMARY KEY (category_id, film_id)
);
DO NOT GO FOR COMMA-SEPARATED VALUES. NEVER.
Having said that. Bear in mind that when you have a so called many-to-many relationship, that is, a relationship where you can have one category with many movies and one movie with many categories, you will always need to generate an additional table.
This table will only need the Primary Keys of each of the other 2 tables and will have a compound key.
So the schema will end up being:
Movies(ID, Title, Description, Category)
Categories(ID, Category)
Movies_Categories(ID_Movie, ID_Category)
In bold are the primary keys.
In order to get all the categories for a movie you will just have to join each of the three tables.
A final comment about having multi-valued fields is that your table will not be in First Normal Form which will, sooner or later, give you lots of headaches.
The last thing to do is have a non normalized table by storing comma separated values.
*You should have a table movies and a table for categories.
You should create a mapping table which will map the movieId to the categoryId*
I have the following setup:
A table with n columns that contain let's say... pizza details. There are 4 kind of pizzas at this point
Until now all pizzas had same details, each detail saved in a column.
But now a new kind of pizza called super pizza appeared, that has 2 more types of details that needs to be saved.
There are 2 ways to do this (that I can think about):
Add to columns to the existing table, and leave them blank/null/whatever for the rest of 4 pizzas types
Create a new table with 3 columns (idPizza, newDetail1 and newDetail2), save pizza as the rest of pizzas, and when I get data join the 2 tables
First option has the disadvantage that I keep useless data for all pizzas except the new type (80% of the table at an average pizzas distribution).
Second option has the disadvantage that each time I get the new kind of pizza I need to make a join. Also the db will be kind of "messy"... having part of pizza element stored in a table and other part in another.
I know that ultimately is a matter of taste but how do you think I should proceed? I incline a bit to first option but a second opinion is welcomed.
As a note: There are lots of entries in the tables (like tens of thousands).
Second note (based on an answer): Can't refactor the "pizza" table, just add to it.
instead of this you can use flat table concept as follows whic hwill be easy for adding no of characteristic in future for new pizzas having some more details
CREATE TABLE pizza
(
id int auto_increment primary key,
name varchar(20),
details varchar(30)
);
INSERT INTO pizza
(name, details)
VALUES
('pizza1', 'nice pizaa'),
('pizza2', 'nice pizza#sqlfiddle');
CREATE TABLE details
(
id int auto_increment primary key,
name varchar(20)
);
INSERT INTO details
(name)
VALUES
('pizza_size'),
('price');
CREATE TABLE pizza_details
(
id int auto_increment primary key,
pizza_id int(10) ,
details_id int(10) ,
details_value varchar(20)
);
INSERT INTO pizza_details
(pizza_id,details_id,details_value)
VALUES
(1,1,'small'),
(1,2,'Rs 20'),
(1,1,'big'),
(1,2,'Rs 50');
and fire the query
select pizza.name as pizza_name,details.name as detail,pizza_details.details_value from pizza_details left join details ON pizza_details.details_id = details.id
left join pizza On pizza_details.pizza_id = pizza.id;
SQL Fiddle
I suggested for use first option. Because 2nd option reserve more resources than 1st option and it will take more time process.
As the disadvantages of 1st option you have mentioned is quite obvious,but when you need more column then add new to that existing table.
Well I suggest just create a table with attributes (idPizza, newDetail) and save data as below
idPizza, newDetail1
1 1 detail
2 2 detail
3 super detail
3 super detail second
MAke idPizza, newDetail1 as primary