I am having a little bit of a problem with setting up a mysql table that will hold a list of categories and subcategories. I am not to sure how to setup the table. Does it need to be 2 separate tables? 1 for the main categories and 1 for the subcategories or can it be all in 1 table? Would something like this work?
Create Table categories (
category_id INT UNSIGNED NOT NULL AUTO_INCREMENT,
sub_id INT UNSIGNED NOT NULL,
name VARCHAR(100) NOT NULL,
PRIMARY KEY (category_id)
)
CREATE TABLE items (
item_id INT UNSIGNED NOT NULL AUTO_INCREMENT,
name VARCHAR(255) NOT NULL,
description VARCHAR(100) NOT NULL,
PRIMARY KEY (item_id),
FOREIGN KEY (category_id) REFERENCES categories (category_id),
FOREIGN KEY (sub_id) REFERENCES categories (sub_id)
)
Will this work or is this completely wrong? Thanks in advance for the help!
If you are 100% sure that you'll only have two levels of categories (main and sub), you can do a few different things. None of them are your proposed solution:
CREATE TABLE categories (
id int not null primary key,
main varchar(64)
sub varchar(64)
);
CREATE TABLE objects (
id int not null primary key,
category_id int,
name varchar(64),
FOREIGN KEY (category_id) REFERENCES categories (id)
);
Want all vehicles?
SELECT *
FROM objects AS o
INNER JOIN categories AS c ON o.category_id = c.id
WHERE c.main = 'vehicles';
Want all roflcopters?
SELECT *
FROM objects AS o
INNER JOIN categories AS c ON o.category_id = c.id
WHERE c.main = 'vehicles' and c.sub='Roflcopters';
If you want something in the "vehicle" category, but not in any of the subcategories of verhicles, just have a category record where main='vehicles' with sub NULL.
Of course, this is not particularly flexible. You're stuck with just two levels of categorization, and there's not a lot of business logic embedded in your category model. But it might be sufficient for your needs.
Two other good, proven, models are the adjacency list model, and the nested set model, both of which are described, with lots of nice example mysql code, over here
It depends.
Are categories and subcategories really two different things? This means categories have no parent, while subcategories are always in a parent category and have no further subs of themselves. Then two tables is ok.
If it's like a tree though, where there are just categories, which can both be children and have children, you should use one table (Google "nested set").
(Or maybe you don't mean category/subcategory but primary category/secondary category, where the secondary category is not fixed to a certain primary category. Electronics + Cycling instead of Cycling->Speedometers. Then you could use one table if it could also be Cycling + Electronics)
It is obviously work. But you may use separate tables.
create table categories
(
categoryId int not null,
categoryName varchar(20) not null,
primary key(categoryId)
);
create table subcategories
(
subcategoryId int not null,
subcategoryName varchar(20) not null,
parentId int not null,
primary key(subcategoryId),
foreign key(categoryId) references categories(categoryId)
);
create tables items
(
item_id int unsigned not null auto_increment,
name varchar(255) not null,
description varchar(100) not null,
primary key(item_id),
foreign key(categoryId) references categories(categoryId),
foreign key(subcategoryId) references subcategories(subcategoryId)
)
Related
Hello and welcome to my question
I have this table:
CREATE TABLE IF NOT EXISTS business(
businessname varchar(250) NOT NULL,
title varchar(250) NOT NULL,
registerdate datetime NOT NULL,
id int NOT NULL,
city varchar(50) NOT NULL,
tk varchar(10) NOT NULL,
number varchar(20) NOT NULL,
branch int,
doy_id int NOT NULL,
PRIMARY KEY (id),
FOREIGN KEY (branch) REFERENCES business(id)
ON DELETE CASCADE ON UPDATE CASCADE,
FOREIGN KEY (doy_id) REFERENCES doy(id_kataxorisis)
ON DELETE CASCADE ON UPDATE CASCADE
)
As you can see this table represents a company, poorly but it does.
The branch column represents the "child" of a company
I want to find (with a select statement) the name of each company and its parent company, if the company has no parent company then it should display NULL.
I have been thinking of this for some time and I don't even know how to begin. Could you please help me?
You can join the table with itself. You must add aliases to each instance of the table the query includes.
For example, you can do:
select
c.id, c.businessname,
p.id, p.businessname
from business c
left join business p on p.id = c.branch
Note: The query uses a LEFT JOIN to ensure you see companies that do not have a parent row. In this case it shows nulls in the place of the parent values.
Been reading up on this (for ages!) and can't get clear picture.
First, if I have two tables (e.g. recipes and ingredients) with a many-to-many relationship and I create a intermediary/relational table, how do I write an SQL query to to find all recipes with, say, bananas in them?
Second, why would I have this third relational table if I can find the same information using JOIN queries without the third tables creation??
Really appreciate a clear, helpful explanation, thanks.
how do I write an SQL query to to find all recipes with, say, bananas in them?
You can do:
select distinct r.id, r.name
from recipe r
join recipe_ingredient ri on ri.id_recipe = r.id
join ingredient i on i.id = ri.id_ingredient
where i.name = 'banana'
Second, why would I have this third relational table if I can find the same information using JOIN queries without the third tables creation?
Since a recipe can have many ingredients, and an ingredient can be related to many recipies the relationship between those two tables is not 1:n but n:m. Therefore, you need an intermediate table, as shown below:
create table recipe (
id int primary key not null,
name varchar(20)
);
create table ingredient (
id int primary key not null,
name varchar(20)
);
create table recipe_ingredient (
id int primary key not null,
id_recipe int not null,
id_ingredient int not null,
quantity double not null,
foreign key fk1 (id_recipe) references recipe (id),
foreign key fk2 (id_ingredient) references ingredient (id)
);
If an ingredient showed up in a single recipe always, the structure would be simpler, as you seem to think. This simpler structure would probably look like:
create table recipe (
id int primary key not null,
name varchar(20)
);
create table ingredient (
id int primary key not null,
name varchar(20),
id_recipe int not null,
foreign key fk3 (id_recipe) references recipe (id)
);
A model like this one is not really practical in this case. You would end up having the same ingredient multiple times. For example, if a cake uses "flour" and bread uses "flour", then "flour" would end up twice in the ingredients table. Not a great idea.
I have below data and using mysql. Person_name is unique and TelephoneNumbers are unique per person.
Person_name1=TelephoneNumber1, TelephoneNumber2, TelephoneNumber3...
Person_name2=TelephoneNumber4, TelephoneNumber5, TelephoneNumber6...
Option 1. Create 1:Many master and child table.
CREATE TABLE Person (
personName varchar(50) NOT NULL,
id int NOT NULL AUTO_INCREMENT,
PRIMARY KEY (id),
UNIQUE KEY personName (personName)
);
CREATE TABLE Telephone (
telephoneNumber int,
mappingId int,
PRIMARY KEY (telephoneNumber),
foreign key(mappingId) references Person(id)
);
Option 2. Create one table with personName, telephoneNumber as Composite Key.
CREATE TABLE
Person_Telephone (
personName varchar(50) NOT NULL,
telephoneNumber int NOT NULL,
PRIMARY KEY(personName, telephoneNumber)
);
Option 1 is it over complicating creating two tables for just two fields?
Option 2 looks perfect and will there be any issues if Option 2 chosen over Option 1?
The option 2 gives you duplicate persons that you must control in every query.
The best is have the entities separate, it's a classic 1-N relation
Since users can have multiple phone numbers, I think 2 tables would be the best solution.
CREATE TABLE person (
PRIMARY KEY (id) AUTO_INCREMENT,
person_name VARCHAR(45) NOT NULL,
);
CREATE TABLE phone_number (
PRIMARY KEY (id) AUTO_INCREMENT,
phone_number VARCHAR(11) NOT NULL,
FOREIGN KEY (person_id) REFERENCES person(id)
)
Now you can simply JOIN the tables like this:
SELECT
t1.id,
t1.person_name,
t2.phone_number
FROM person t1
LEFT JOIN phone_number t2
ON (t1.id = t2.person_id);
The following query was successful but when I enter null values into order id and different values(those which do not exist in the column) for item id, the order id is still getting incremented. How to retain the same order id? Is there a problem with the way the foreign key has been stated?
CREATE TABLE orders(
orderid int not null auto_increment,
itemid int not null,
quantity int not null,
tot_price int not null,
cid int not null,
code varchar(10),
order_time time,
order_date date ,
constraint order_pk primary key (orderid, itemid),
foreign key (itemid) references items(itemid),
foreign key (cid) references customer(cid),
foreign key (code) references coupon(code)
);
The problem stems from trying to do a one-to-many (order to items) relationship in a single table. This will end badly. You need two. One for the order, one for the items in the order. For good or bad, this is how relational databases do lists.
CREATE TABLE orders (
orderid int not null primary key auto_increment,
cid int not null references customer(cid),
code varchar(10) references coupon(code),
when_ordered datetime,
INDEX(when_ordered)
);
CREATE TABLE items_in_an_order (
orderid int not null references orders(id),
itemid int not null references items(id),
quantity int not null,
price_paid int not null
);
quantity moves to items_in_an_order. I changed total_price to the more descriptive price_paid which is likely more descriptive of what you want to be storing. This will let you produce receipts.
order_date and order_time were unnecessarily split into two columns. This makes comparison and sorting awkward. Putting them together into one DATETIME column and indexing it will let you do sorting by date/time and check if an order is inside a date/time range.
To get all the items in an order, do a join.
SELECT items.itemid
FROM items
JOIN items_in_an_order io ON io.itemid = items.id
WHERE io.orderid = ?
To find all the orders an item is in, also do a join.
SELECT orders.id
FROM orders
JOIN items_in_an_order io ON io.orderid = orders.id
WHERE io.itemid = ?
I have two tables for one is category and another one is sub-category. that two table is assigned to FK for many table. In some situation we will move one record of sub-category to main category. so this time occur constraints error because that key associated with other table. so i would not create this schema.
so now i plan to create category and sub-category in same table and create relationship table to make relationship between them.
category table:
id(PK,AUTO Increment),
item===>((1,phone),(2.computer),(3,ios),(4,android),(5,software),(6,hardware)).
relationship table:
id,cate_id(FK),
parentid(refer from category table)===>((1,1,0),(2,2,0),(3,3,1),
(4,4,1),(5,5,2),(5,5,3)).
in my side wouldnot go hierarchy level more than three.
if we easily move to subcategory to main category ex:(4,4,1) to (4,4,0) without affect any other table. is this good procedure?
if we will maintain millions record, will we face any other problem in future?
have any another idea means let me know?
There might be a problem if you have multiple levels in the tree, and want to find all the subcategories of any category. This would require either multiple queries, or a recursive one.
You could instead look into the "Nested Sets" data-structure. It supports effective querying of any sub-tree. It does have a costly update, but updates probably won't happen very often. If need be, you could batch the updates and run them over night.
create table Category (
Id int not null primary key auto_increment,
LeftExtent int not null,
RightExtent int not null,
Name varchar(100) not null
);
create table PendingCategoryUpdate (
Id int not null primary key auto_increment,
ParentCategoryId int null references Category ( Id ),
ParentPendingId int null references PendingCategoryUpdate ( Id ),
Name varchar(100) not null
);
If you have a small number of categories, a normal parent reference should be enough. You could even read the categories into memory for processing.
create table Category (
Id int not null primary key auto_increment,
ParentId int null references Category ( Id ),
Name varchar(100) not null
);
-- Just an example
create table Record (
Id int not null primary key auto_increment,
CategoryId int not null references Category ( Id )
);
select *
from Record
where CategoryId in (1, 2, 3); -- All the categories in the chosen sub-tree
How about creating one table as following:
categories(
id int not null auto_increment primary key,
name char(10),
parent_id int not null default 0)
Where parent_id is a FK to the id, which is the PK of the table.
When parent_id is 0, then this category is a main one. When it is > 0, this is a sub category of this parent.
To find the parent of a category, you will do self-join.