Having extra columns in join between 3 tables MySQL - mysql

I have 3 tables : Car, Client and Car_client the latter is a junction table between car and client, since as I said Car_Client is a junction table this means the relationship between car and client is many to many. Tables have this structure:
_____________________ ___________________ ______________________
| Car | | Client | | Car_Client |
|___________________| |_________________| |____________________|
| license_plate (PK)| | Name | | license_plate(fk) |
| Model | | Surname | | Id_Code(fk) |
|___________________| | Id_Code (PK) | |____________________|
| Phone |
|_________________|
Now, what I am trying to achieve is to allow the user to research the client by name. When the name is searched I want to show all the info about the car he owns and his personal info. So basically like a select * from Car, Client but just for a specific name.To achieve this I tried different methods, the one that works best, although not perfectly is this one :
SELECT * FROM
Car_Client car_cli
INNER JOIN Car ON ( car_cli.license_plate = car.license_plate)
INNER JOIN Client ON ( car_cli.Id_Code = Client.Id_Code)
WHERE
Car_Client.Id_Code in (SELECT Id_Code FROM Client WHERE Name = 'emanuele');
The problem with this solution is that I have two extra columns of license_plate and Id_Code

SELECT Client.*, Car.* FROM
Car_Client car_cli
INNER JOIN Car ON ( car_cli.license_plate = car.license_plate)
INNER JOIN Client ON ( car_cli.Id_Code = Client.Id_Code)
WHERE
Car_Client.Id_Code in (SELECT Id_Code FROM Client WHERE Name = 'emanuele');

Related

MySQL table relations - join if field has value

There could be X different tables in my system and one table that stores all relation data of those tables. For example the database could look like this
-------------------------- -----------------------------------
| Table fruits | | Table drinks |
-------------------------- -----------------------------------
| id | name | | id | name |
-------------------------- -----------------------------------
| 1 | banana | | 1 | strawberry apple cocktail|
| 2 | apple | | 2 | banana juice |
| 3 | strawberry | | 3 | cola |
-------------------------- -----------------------------------
--------------------------
| table food |
--------------------------
| id | name |
--------------------------
| 1 | apple pie |
--------------------------
And the table for the relations contains the id and the table name from both entries.
--------------------------------------------------
| table relations |
--------------------------------------------------
| id | table_1 | id_1 | table_2 | id_2 |
--------------------------------------------------
| 1 | fruits | 1 | drinks | 2 | banana + banana juice
| 2 | fruits | 2 | drinks | 1 | apple + s.a. cocktail
| 3 | fruits | 3 | drinks | 1 | strawberry + s.a cocktail
| 4 | food | 1 | fruits | 2 | apple pie + apple
| 5 | drinks | 3 | food | 1 | if someone wants to mix it
--------------------------------------------------
If I have a drink (strawberry apple cocktail) I want to get all fruit ids that belong to it (strawberry and apple) and the other way around when I have a fruit (strawberry) I would like to query for all related drink ids.
So I need one query structure to find both sides and since it is all dynamic I can't know if the fruit is in table_1 or table_2 (otherwise it would be simple)
I would like to have something like this (attention pseudocode) to query all ids from drinks that contain bananas (table: fruits, id: 1)
SELECT id
FROM drinks
LEFT JOIN relations AS rel ON drinks.id = (rel.table_1 == drinks)? rel.id_1 : rel.id_2
WHERE
((rel.id_1 = '1' AND rel.table_1 = 'fruits') OR ( rel.id_2 = '1' AND rel.table_2 = 'fruits' ))
My issues
When I join my relation table only one time, I would have to query two times since I don't know if I have to join it on id_1 or id_2
When I do 2 Joins like this
Select * from drinks
LEFT JOIN relations AS relation1 ON drinks.id = relation1.id_1
LEFT JOIN relations AS relation2 ON drinks.id = relation2.id_2
WHERE
( (relation1.id_1 = '1'
AND relation1.table_1 = 'fruits')
OR ( relation2.id_2 = '1'
AND relation2.table_2 = 'fruits' )
OR ( relation1.id_2 = '1'
AND relation1.table_2 = 'fruits')
OR ( relation2.id_1 = '1'
AND relation2.table_1 = 'fruits'))
I can search for everything from both sides (have drinks -> receive fruits / have fruit -> receive drinks) but I get also the drink with the same Id like the fruit
I would like to avoid to select * from relations since I build the query with php with other conditions like fruit name, dateCreated and so on and I would have to restructure the entire query if it contains relations
You can download the mysql dump here to test it. I hope someone could be so kind to help me.
Thank you and sry for my bad english
Your problem is in your design, the drink table has many-to-many relation with fruit table, so you should separate fruit_drink_relation's table.
The same many-to-many relation exist for fruit_drink_food_relation's table.
To look for food, query the second relation's table, otherwise, the first relation table is enough.
Utterly bad design there.
See, the Relational Database Management Systems possess the powerful mechanism of keeping and enforcing consistent (!) relationships between entities (represented as records in the tables).
Why not use it as it is?
You got n..n (many-to-many) relationships, not more than that, as seen from examples.
There's a more-than-common pattern for it, the relation table that essentially consists of two columns both of which are foreign keys to the entities you'd need to connect together:
CREATE TABLE fruits_juices (
fruit_id INT,
juice_id INT
FOREIGN KEY fruit_id
REFERENCES fruits(id),
FOREIGN KEY juice_id
REFERENCES juices(id)
)
Do that for each relation you need - and this it.
And that is nothing bad in creating a couple of relationships - that's the way RDBMS supposed to work (hence what they're best at).
Don't try to be unnecessary versatile: your use cases don't demand that whatsoever.
Too one-for-all solutions are usually not good in all the cases they suppose to cover and have an additional maintenance cost to keep them from falling apart (data consistency, in your case)
I think you want a snowflake schema.
Looks like currently you are -in the ugly- half way of that.

How to connect and relationship between these two tables?

I have two tables:
users (user_id, user_name, user_email, user_pass)
&
toys (name, box)
I need each user to have their own toys table. Basically the table for users is for my login form and the toys is where the user choose the toys once they login.
Add an extra table that have FK (foreign keys) to both Users and Toys, that acts as the table for the many-to-many relation
i.e. create a table called user_toys that has toy_id and user_id combination per row. Then if you want to get all the toy names for a particular user, you can just do
SELECT t.name
FROM Toys t,
User_toys relation,
WHERE relation.toy_id = t.toy_id
AND relation.user_id = :user_id
(Note, you don't need to join to the Users table if you already have the user_id in the relation table)
If each toy can only belong to one user (1-to-many), then adding an extra column for user_id FK on the Toys table would suffice. But sounds like from your question each user have their independent set of toys to pick.
reference: https://en.wikipedia.org/wiki/Associative_entity
hello you need one field in table Toy to make your table become relation, here is my schema based on yours
here is toys
+--------+-------------+--------------+-----+
| id_box | id_box_user | id name | box |
+--------+-------------+--------------+-----+
| 1 | 1 | Name toys 1 | box |
| 2 | 2 | Name toys 3 | box |
+--------+-------------+--------------+-----+
then this is user
+---------+-------------+------------+-----------+
| user_id | user_name | user_email | user_pass |
+---------+-------------+------------+-----------+
| 1 | user name 1 | email | pass |
| 2 | user name 2 | email | pass |
+---------+-------------+------------+-----------+
and you need query like this to get all data with spesific user
SELECT * FROM user a, toys b where a.user_id=b.id_box_user_id
but for spesific user use this
SELECT * FROM user a, toys b where a.user_id=b.id_box_user_id and a.user_id='variable which store session'
and this is the screen shot

MySQL Intermediate-Level Table Relationship

Each row in Table_1 needs to have a relationship with one or more rows that might come from any number of other tables in the database (Table_X). So I set up an intermediate table (Table_2) where each row contains an id from Table_1, and the id from Table_X. It also has its own auto increment id since none of the relationships will be exclusive and therefore both the other ids will not be unique in the table.
My problem now is that when I retrieve the row from Table_1 and would like to see the information from each related row from Table_X, I don't know how to get it. At first I thought I could create a column for the exact name of Table_X for each row in Table_2 and have a second SELECT statement using that information, but I've been seeing inklings about things such as foreign keys and join statements that I think I need to get into. I'm just having trouble sorting it all out. Do I even need Table_2?
This probably isn't overly complicated, but I'm just getting into MySQL and this is the first real challenge I've encountered.
Edit to include requested information: If I understand correctly, I think I'm dealing with a many to many relationship. Table_3 has games; Table_1 has articles. An article can be about multiple games, and a game can also have multiple articles written about it. The only other possibly pertinent information I can see is that when a new article is made, every game that will be related to it is decided all at once. But the list of articles related to a given game can grow over time as more articles are written. That's probably not especially important, however.
If I understood correctly You are talking about one to many relationship in database (for example: one person can have multiple phone numbers), You can store data in two separate tables persons and phones.
Persons:
|person_id|person_name |person_age |
| 1 | Bodan Kustan| 28 |
Phones:
|phone_id |person_id |phone_number|
| 1 | 1 | 31337 |
| 2 | 1 | 370 |
Then you can execute query with Join:
SELLECT * FROM `persons`
LEFT JOIN `phones` ON `persons`.`person_id` = `phones`.`person_id`
WHERE `persons`.`person_id` = 1;
And it will return to You list of persons with phone numbers:
|person_id|person_name |person_age |phone_id |person_id |phone_number|
| 1 | Bodan Kustan| 28 | 1 | 1 | 31337 |
| 1 | Bodan Kustan| 28 | 2 | 1 | 370 |
Another possibility is Many to Many relationship (for example: Any person can love pizza, and pizza is not unique for that person), then You need third table to join tables together person_food
Persons:
|person_id|person_name |person_age |
| 1 | Bodan Kustan| 28 |
Food:
|food_id |food_name |
| 1 | meat |
| 2 | pizza |
Person_Food
|person_id |food_id |
| 1 | 2 |
Then you can execute query with Join:
SELLECT * FROM `persons`
LEFT JOIN `person_food` ON `person`.`person_id` = `person_food`.`person_id`
LEFT JOIN `food` ON `food`.`food_id` = `person_food`.`food_id`
WHERE `persons`.`person_id` = 1;
And it will return data from all tables:
|person_id|person_name |person_age |person_id |food_id |food_name |
| 1 | Bodan Kustan| 28 | 1 | 2 | pizza |
However sometimes you need to join n amount of tables to join, then You could use separate table to hold information about relation. My approach (I don't think it's the best) would be to store table name next to relation (for example split mobile phones and home phones into two separate tables):
Persons:
|person_id|person_name |person_age |
| 1 | Bodan Kustan| 28 |
Mobile_Phone:
|mobile_phone_id |mobile_phone_number |
| 1 | 31337 |
Home_Phone:
|home_phone_id |home_phone_number |
| 1 | 370 |
Person_Phone:
|person_id |related_id |related_column |related_table |
| 1 | 1 | mobile_phone_id | mobile_phone |
| 1 | 1 | home_phone_id | home_phone |
Then query middle table to get all relations:
SELECT * FROM person_phone WHERE person_id = 1
Then build dynamic query (pseudo code, not tested -- might not work):
foreach (results as result)
append_to_final_sql = "LEFT JOIN {related_table}
ON {related_table}.{related_column} = `person_phone`.`related_id`
AND `person_phone`.`related_table` = {related_table}"
final_sql = "SELECT * FROM `persons` "
+ append_to_final_sql +
" WHERE `persons`.`person_id` = 1"
So Your final SQL would be:
SELECT * FROM `persons`
LEFT JOIN `person_phone` ON `person_phone`.`person_id` = `person`.`person_id`
LEFT JOIN `mobile_phone` ON `mobile_phone`.`mobile_phone_id` = `person_phone`.`related_id` AND `person_phone`.`related_table` = 'mobile_phone'
LEFT JOIN `home_phone` ON `home_phone`.`home_phone_id` = `person_phone`.`related_id` AND `person_phone`.`related_table` = 'home_phone'
You only need Table2 if entries in Table_x can be related to multiple rows in Table1 - otherwise a simple key for Table1 will suffice.
Look into joins - very powerful, flexible and fast.
select * from Table1 left join Table2 on Table1_id = Table2_table_1_id
left join Table_X on Tablex_id = Table2_table_x_id
Look at the output and you'll see that it returns all table_x rows with copies of the Table1 and Table2 fields.

EAV table to flat table

Say I have a table eav like this (SQL Fiddle):
| Person_ID | PAttribute_ID | Value |
| 1 | 1 | Flat Street 1 |
| 1 | 2 | 634-5789 |
And want to create a query that returns all attributes as a flat table (e.g. to export to a spreadsheet)
Is there a better way than just manually left joining for all the attributes? Like this:
SELECT id , address.Value AS adressV, telephone.Value as telephoneV
FROM person
LEFT JOIN eav AS address ON address.Person_ID = person.id AND address.PAttribute_ID = 1
LEFT JOIN eav AS telephone ON telephone.Person_ID = person.id AND telephone.PAttribute_ID = 2;
With 2 attributes that's feasible, with 50 attributes you get an un-understandable query.

SQL commands for two tables, which need primary and foreign key

I have table structures as follows:
Table Person :
+-------+--------+
| sno | sname |
+-------+--------+
| 1 | Bhanu |
| 2 | Raghu |
| 3 | Bunny |
| 4 | Shyam |
+-------+--------+
Table Friend :
+------+---------+
| sno | Friend |
+------+---------+
| 1 | 2 |
| 2 | 1 |
| 3 | 4 |
| 4 | 3 |
+------+---------+
Bhanu is friend of Raghu, vice versa.
Bunny is friend of Shyam, vice versa.
If I give the 'Bhanu' name from person table, I should be able to get his friend name as well. Which is mentioned in Friend table with respect to his sno values from person table.
Please do help me in performing this read operation with this kind of database.
You'll need to access the person table twice, and so will need aliases. I suggest this table structure first:
person (id, name)
friend (from_person_id, to_person_id)
This is much the same as your table structure, but the names are a bit clearer.
Now you could have something like:
SELECT
p2.name
FROM
friend
INNER JOIN person p1 ON (p1.id = friend.from_person_id)
INNER JOIN person p2 ON (p2.id = friend.to_person_id)
WHERE
p1.name = 'Bhanu'
;
That lists all the friendships going from "from" to "to". You might additionally want to list all the friendships going the other way, in which case you could add OR p2.name = 'Bhanu'.