What database technique should I use? - mysql

I am new to databases. This is for a class. I am using MySQL. I will be accessing the database with PHP. I have two tables already. TableA is for products. TableB is for US States. I want to have data about sales of each product in each state. I have considered this is a many to many relationship.
Technique idea #1:
I have considered making a third table, TableC, that has a column for the state names and a column for each product. My issue with this is that I don't know how create a relationship between the product rows in TableA and the product columns in TableC. If I add a product to TableA I want it to automatically add the column in TableC.
Technique idea #2:
Add the product columns to TableB. Same issue as above. Also, seems like a worse design.
Are one of these techniques the right way to do this or is there another technique?

The art and science of making a good schema revolves around finding the best place to put something, or in many cases, the least inconvenient.
Putting sales data in a table that's intended for geographic information is almost always a mistake. Keep your tables focused on one entity, and where information there exists only when related to other tables, make a "join table" that connects the two and put that data there.
For example:
CREATE TABLE products (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(255)
);
CREATE TABLE states (
id INT PRIMARY KEY AUTO_INCREMENT,
code CHAR(2),
name VARCHAR(255)
);
CREATE TABLE state_sales(
id INT PRIMARY KEY AUTO_INCREMENT,
state_id INT NOT NULL,
product_id INT NOT NULL,
quantity INT
);
You can extend that later to include things like the date/month/quarter the sales happened in and so forth.

Related

Is it possible to remove an ID where it is not used?

I have a table with the following structure
CREATE TABLE Products (
id INT(6) UNSIGNED AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(30) NOT NULL,
code VARCHAR(30) NOT NULL UNIQUE,
warranty TINYINT(1) NOT NULL,
producing_country VARCHAR(50),
)
Each product in my table has a unique code and This products is also known in stock as this codes
Codes are something like this: (AR-X22 , RF-3654, ...)
My question is can i remove the ID cloumn in this table? Because it has no special application
And does it hurt if I want to use the code column instead of id in join ?
Its good practice to have a table with an id INT AUTO_INCREMENT and PRIMARY KEY.
It makes sure each row is unique. If other programmers come and look at your table they will expect to see an id column.
Having a VARCHAR as a unique row key is is asking for trouble. There are all sorts of encoding troubles and things that can make strings as identifiers unreliable.
For example: "ABX-112" and "ABX -112" (space hidden in there)
If you just don't want to see ID column do like ravioli states below and just make a new view and not show it.
Good luck.
Your id column is specified as your PK, which means it's used to uniquely identify that row in your table. It looks like it's an identity-type field, which should take care of the uniqueness requirement.
If you want to use code as your new "id" field, that should be fine as long as you make sure it's a unique value when you add rows. It shouldn't have any effect on joins as long as you update your other tables to use the new code field.
I don't know how easy it is to fiddle with PK's on a table that already has data. Your best bet is to create a new table without the id field and populate it using the data in your current table.
If it's just a matter of not wanting to see / deal with an id field you never use, you can always create a view and exclude that field from being returned.
As per my understanding, You want to remove Id from the table and want to use Product code at that place.
A table relationship is based on the primary and foreign key constraints and it is not necessary that every time you have to Id column as primary key.
If you have product code and which will always be unique and not null
then you can use Code as the primary key for the table rather then
unnecessary Id column.
It will also work if you do not create a column wither primary.
Thanks.

How to design mysql tables that follow multiple values from each other

I am trying to make something of a vacation website where a user can follow certain vacations.
Right now there are 2 tables, one for vacations and one for users.
I want to make it so when a user decides to follow a vacation, it will be somehow associated with him like a column of "followedVacations" that would contain the ids of the vacations he's following.
Problem is what if he is following multiple vacations? how do i store that information with the user, or alternatively store on the vacation entry which users are following it?
I am using mysql, react and node if that has any relevancy
I don't know how to make it work so i couldn't really try anything
iv'e got no code to show because i dont know how to approach this on a table and schema design level
I'm basically looking for the correct way to do this.
Edit: Would it be possible to also have amount of followers on the vacation table?
A standard approach here would be to create a third junction table which relates users to vacations and vice-versa. So, you might have the following three tables:
CREATE TABLE users (
id INT NOT NULL,
name VARCHAR(50),
PRIMARY KEY(id)
)
CREATE TABLE vacations (
id INT NOT NULL,
name VARCHAR(50),
location VARCHAR(50),
price DECIMAL(10,2),
PRIMARY KEY (id)
)
CREATE TABLE user_vacations (
user_id INT NOT NULL,
vacation_id INT NOT NULL,
PRIMARY KEY (user_id, vacation_id)
)
Note that the junction user_vacations table mainly exists to relate users to vacations. All the metadata associated with a user or vacation would continue to be stored in your current two tables which already exist.

"many to many to many" relation

I have a simple database of cosmetics. Each product may consist of multiple ingredients. Therefore it is a simple many to many relation and currently I have a database like this:
CREATE TABLE `products` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`name` TEXT NOT NULL,
PRIMARY KEY (`id`),
);
CREATE TABLE `ingredients` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`name` TEXT NOT NULL,
PRIMARY KEY (`id`),
);
CREATE TABLE `ingredient_to_product` (
`ingredient_id` INT UNSIGNED NOT NULL,
`product_id` INT UNSIGNED NOT NULL,
PRIMARY KEY (`ingredient_id`, `product_id`),
INDEX (`product_id`)
);
However, some ingredients can have many different names. For example: "LINALOOL ESSENTIAL OIL", "LINALYL ALCOHOL" and "3,7-DIMETHYL-1,6-OCTADIEN-3-OL" refers to the same ingredient.
When I am presenting one product, I would like to keep ingredient name as on product label. So in case of one product it will be "LINALYL ALCOHOL" and in case of another product it may be something other, but referring to identical ingredient.
Now I would like to query database for all names of the product by specifying one of its names or by its ID, however how one ID could refer to many names? Do I have to keep two tables: one for specific ingredient in general and another table just for names (relation many names to one ingredient)? Is there any better way?
Ingredients
ID (int) (pkey) (ai)
Name (varchar)
Synonyms
ID (int) (pkey) (ai)
IngredientID (int) (foreign key maps to: Ingredients.ID)
Name (varchar)
Flag (optional; sample values: IUPAC Name, Common Name, Spanish Name, ...)
So yes, for the rules you described, you will at minimum have a primary name, and then a synonym table using the Ingredients.ID
I also introduced a Flag field so that you can programmatically choose when to use a synonym rather than just hard-coding it all the time. For example, if you're listing a product flagged as an industrial chemical, it would be programmed to pull the IUPAC* name
*IUPAC refers to conventions for naming chemicals, and is used by professional chemists almost always, but almost never used in consumer supermarkets: http://www.chem.uiuc.edu/GenChemReferences/nomenclature_rules.html
I suppose the good news is that one name cannot be used for multiple different ingredients, right?
So yes, you probably need an "ingredient name" table, something like
`name` TEXT NOT NULL,
`ingredient_id` INT UNSIGNED NOT NULL
(I'd probably just use name as the PK here, but if your design calls for always using surrogates then also add ingredient_name_id I guess...)
And then the details of the ingredient (except name) would still go in ingredient table. (You could keep a default name in the ingredient table as well, but I wouldn't. If you need that concept, I'd consider adding a "default flag" to the ingredient name table or something like that.)
Since you want to know the name used for each ingredient by a given product, you would replace your current "ingredient to product xref" with an "ingredient-name to product xref".
Why don't you create a separate table for other ingredient name/chemical names, etc. and have it connected with the product id so it can be used separately when needed, and to avoid having any NULL values in your main table.

Insert Data into multiple tables in MySQL

Consider two tables User and UserDetails
User (UserID,Name,Password)
UserDetails(UserID,FullName, Mobile Number,EMail)
First I will enter details into User table
Then Afterwards I wish to enter details into UserDetails Table with respect to primary key of first table i.e., UserID which is autoincremented.
consider this scenario..
User: (101, abc, xyz), (102,asd,war)
Now i want to store details in second table with respect to Primary key where UserID= 102
How can I accomplish this?
Start over with the design. Here is a start that runs through and doesn't blow up. Do the same for email. Keep data normalized and don't cause unnecessary lookups. When you have a lot of constraints, it is a sign that you care about the quality of your data. Not that you don't without constraints, if they are un-constrainable.
We all read on the internet how we should keep main info in one table and details in another. Nice as a broad brush stroke. But yours does not rise to that level. Yours would have way too many tables. See Note1 at bottom about about Entities. See Note2 at bottom about performance. See any of us with any broad or specific question you may have.
create table user
( userId int auto_increment primary key,
fullName varchar(100) not null
-- other columns
);
create table phoneType
( phoneType int auto_increment primary key, -- here is the code
long_description varchar(100) not null
-- other columns
);
create table userPhone
( id int auto_increment primary key,
userId int not null,
phone varchar(20) not null,
phoneType int not null,
-- other columns
CONSTRAINT fk_up_2_user FOREIGN KEY (userId) REFERENCES user(userId),
CONSTRAINT fk_up_2_phoneType FOREIGN KEY (phoneType) REFERENCES phoneType(phoneType)
);
Note1:
I suspect that your second table as you call it is really a third table, as you try to bring in missing information that really belongs in the Entity.
Entities
Many have come before you crafting our ideas as we slug it out in design. Many bad choices have been made and by yours truly. A good read is third normal form (3NF) for data normalization techniques.
Note2:
Performance. Performance needs to be measured both in real-time user and in developer problem solving of data that has run amok. Many developers spend significant time doing data patches for schemas that did not enforce data integrity. So factor that into performance, because those hours add up in those split seconds of User Experience (UX).
You can try this:-
INSERT INTO userDetails
(SELECT UserID, Name FROM User WHERE USerID= 102), 'Mob_No', EMail;

Multitable constraints for a column value in sql database

I have a three tables, a project table, there may be many projects, a subjects table, where each project will have many subjects and a condition table where each subject will have a condition and a project may have many conditions.
How to restrict the condition that the subjects can have based on the conditions that the project is linked to given that the subject must be in one of the projects.
Hope that makes sense. Also, I am thinking of using sqlite but if it is not possible to do something like this with the database system does there exist one that can? Preferebly free and sql based ie mysql or postgresql.
Thanks.
edit: some examples;
project A has conditions 1, 2 and 3. All are drawn from the condition table which has conditions 1,2,3,4,5. Now subject X is part of project A so should only be allowed to assume conditions 1,2,3 NOT 4 or 5.
Is this possible?
Looks like you need something similar to this:
The key aspect of this design the the usage of identifying relationships and the resulting composite keys. This allows us to migrate PROJECT.PROJECT_ID:
not just directly to SUBJECT
but also through CONDITION and then to SUBJECT.
Both of these "paths" of migration eventually get merged into the same field (note FK1,FK2 in front of SUBJECT.PROJECT_ID), which ensures that when a subject is connected to a condition, they both must be connected to the same project.
create table Condition(
Id int not null, --PK
Description varchar(50)
)
create table ProjectCondition(
Id int not null, --PK
ProjectId int not null, -- FK to Project PK#
ConditionId int not null -- FK to Condition PK
)
create table ProjectSubject(
Id int not null, --PK
ProjectId int not null, -- FK to Project PK
SubjectId int not null -- FK to Subject PK
)
create table ProjectSubjectCondition(
Id int not null, -- PK
ProjectConditionId int not null -- FK to ProjectContion PK
)
Assumptions:
Subject has an existence separate from Project (i.e. there is a
Subject table somewhere)
Condition is the same
(Doesn't make much difference if they're wrong.)
By linking the ProjectSubjectCondition to the ProjectConditions the condition of a subject for a project must be a condition of the project.
Cheers -