user498982
user498982

Reputation:

mySQL database structure

I've worked with mysql for some time but have never had to do anything anywhere near complicated. I'm working on a new project and need a little push in the right direction. Lets say I want to have a table that stores cats. Lets say I want to store the cats name, and food that the cat likes. Then lets say I want to query all cats that like fish, milk, and mice. I don't want to have the 'cats' table have rows for 'fish' 'milk' 'mice' that can be yes or no or 1 or 0. I think want I'm looking for is having a separate 'foods' table and then use the join statement. But I have no clue where to start looking or what to search for. Another way to think about this would be if you had a blog, and wanted posts to have categories. How would I store which posts are in which categories, and how would I query for posts by category?

I realize this is probably a very basic question, and would be happy with even a link to a tutorial explaining the structure / commands needed to pull this off! Thanks a lot!

Upvotes: 0

Views: 153

Answers (3)

simshaun
simshaun

Reputation: 21466

Table: cats
id
name

Table: foods id name

Table: cat_food cid (Cat ID) fid (Food ID)

Query: Select cats that like fish SELECT name FROM cats c INNER JOIN cat_food cf ON cf.fid = 2 -- Assuming food ID#2 is 'fish'
Query: Select cats that like fish, milk, or mice SELECT c.name FROM cats c INNER JOIN cat_food cf ON cf.fid IN (1, 2, 3) GROUP BY c.name
SCHEMA CREATE TABLE IF NOT EXISTS cats ( id int(10) unsigned NOT NULL AUTO_INCREMENT, name varchar(255) COLLATE utf8_unicode_ci NOT NULL, PRIMARY KEY (id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=3 ;

INSERT INTO cats (id, name) VALUES (1, 'Sassy'), (2, 'Tiger');

CREATE TABLE IF NOT EXISTS cat_food ( cid int(10) unsigned NOT NULL COMMENT 'Cat ID', fid int(10) unsigned NOT NULL COMMENT 'Food ID', UNIQUE KEY cid_fid (cid,fid), KEY fid (fid) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

INSERT INTO cat_food (cid, fid) VALUES (1, 1), (2, 2), (1, 3);

CREATE TABLE IF NOT EXISTS foods ( id int(10) unsigned NOT NULL AUTO_INCREMENT, name varchar(255) COLLATE utf8_unicode_ci NOT NULL, PRIMARY KEY (id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=4 ;

INSERT INTO foods (id, name) VALUES (1, 'Fish'), (2, 'Milk'), (3, 'Mice');

ALTER TABLE cat_food ADD CONSTRAINT cat_food_ibfk_2 FOREIGN KEY (fid) REFERENCES foods (id) ON DELETE CASCADE, ADD CONSTRAINT cat_food_ibfk_1 FOREIGN KEY (cid) REFERENCES cats (id) ON DELETE CASCADE;

Upvotes: 2

Tyler Treat
Tyler Treat

Reputation: 14988

You are thinking right. You want two tables, a "Cats" table and a "Food" table. Your Food table would have some sort of primary key that your Cats table would reference as a foreign key. You could do a query perhaps like this:

SELECT * FROM cats WHERE food_id = 5

To understand how JOIN works in SQL, I would look through here.

Upvotes: 0

EnabrenTane
EnabrenTane

Reputation: 7466

I can only offer the rails example.

In rails

I a perfect world where every post had 1 category

And you would see SQL like

Posts.find_all_by_category_id(Category.find_by_topic("sports").id)
# May generate 
SELECT ALL from `post`.* WHERE `category_id` = `7` 


class Category < ActiveRecord::Base
    has_many => :posts
end

class Post < ActiveRecord::Base
    belong_to => :categories
end

In the real world its a many to many relation

   class Category < ActiveRecord::Base
       has_and_belongs_to_many => :posts
   end

   class Post < ActiveRecord::Base
       has_and_belongs_to_many => :categories
   end

and rails would make the many to many join table for you behind your back

You would then go Category.find_by_topic("sports").posts to recover all the posts with a category of sports.

I don't know the detailed mySQL generated of the top of my head for how they do many to many relations.

Upvotes: 0

Related Questions