Implement and query MYSQL foreign key which refers to two tables - mysql

I have two tables Hotels and Activities
Hotels
id | name |
1 | hilton |
2 | taj samudra |
3 | galadari |
Activities
id | name |
1 | air balloon |
2 | whale watching |
3 | jungle safari |
also I have a another table Tour
id | starting_location_id | starting_location_type
1 | 1 | hotel
2 | 1 | activity
user can start the Tour from hotel or activity.
What I want is to pass the id and need to get the data like this using a join
id | name
1 | hitlon
2 | air baloon
If I future explain, I want a foreign key which can refer to multiple tables.
Note :- This is not implemented yet. I want to implement this kind of scenario. I want to pass the id in the Tour table and need to get the associated data for that record.
Is this possible to in MYSQL?

You can try below -
DEMO
select t1.id,coalesce(h.name,a.name) as name
from tour t1
left join hotels h on t1.starting_location_id=h.id and starting_location_type='hotel'
left join Activities a on t1.starting_location_id=a.id and starting_location_type='activity'
OUTPUT:
id name
2 air balloon
1 hilton

Related

how can we add two field in same column in sql table?

i want to create a database that consists all products rating and notes purchase by user
suppose that i create a table name "Users_rating_product" that consists some column
user_id ->INT
company->Varchar
product1 -> 3 (rating of product out of 5)|(review of product)
product2-> 4(rating)|(some review)
i want to know how can i do it in mysql . i'm using phpmyadmin for database creation
table looks like
user_id | company |Ac | TV | fridge
1 | goderaj |3 ,take more power |4,less power |5,efficient
i want to know how can i do this so that both rating and notes for product display in same column
For this you'll need a separate table. Call it ProductRating. Put a unique key (ID) to the table and reference that key to your Users_rating_product table.
For example:
Users_rating_product:
user_id | company |Ac | TV | fridge
1 | goderaj |1 | 2 | 3
2 | somecomp |4 | 5 | 6
ProductRating
ID | Rating | Review
1 | 3 | Take more power
2 | 4 | less power
3 | 5 | efficient
4 | 5 | excellent
5 | 1 | awful
6 | 3 | average
There are many ways that you can achieve your functionality.
but this is not standard format to write queries.
you can have comma seperated column in your database like this
user_id | company |Ac_mapping_id
1 | goderaj |1,REview for Ac
for Seperate two values you can do like this
PARSENAME(REPLACE(String,',','.'),2) 'Name'
for Detail Reference for splitting two values you can refer :
click To refer
Better Way is to store Product description in different table.
You can easily write queries to retrieve your data
user_id | company |Ac_mapping_id | TV_mapping_id | fridge_mapping_id
1 | goderaj |1 | 2 | 3
& store all the ratings & reviews in mapping table like this
Ac_mapping_id | Rating |Review
1 | 1 |abcd
So on for the other table.
For Retrieving all the data just Use Left outer join
Select
*
from
Users_rating_product mm
Left outer join Ac_mapping_table ac on ac.ac_mapping_id = mm.ac_mapping_id
.....so on

One-to-one relation through pivot table

Okay so I have a soccer website im building when a user signs up they get a team and and 6 different stadium to chose from. so I have a teams table:
----------------------------------------
| user_id | team_name | stadium_id |
----------------------------------------
| 1 | barca | 2 |
----------------------------------------
Then I decided to make the stadiums its own table
----------------------------------------------
| id | name | capacity | price |
----------------------------------------------
| 1 | Maracana | 50000 | 90000 |
------------------------------------------------
| 2 | Morombi | 80000 | 150000 |
------------------------------------------------
to get the teams arena name I would have to get the arena_id from the teams table and then fetch the arena name with the id. Now I don't think this is very efficient so I gave it some thought and I think the best solution is adding a pivot table like so:
| id | arena_id | team_id |
---------------------- ----------------
| 1 | 2 | 1
--------------------------------------|
| 2 | 1 | 2
--------------------------------------|
I usually think of pivot tables as tables for many to many relationships not one to one relationships. Is using a pivot table in this instance the best solution or should I just leave the implementation I'm currently using?
You don't need to use a pivot-table for this. It can either be a One-To-One or a One-To-Many relationship. It's a One-To-One if every user/team does only relate to one stadium (no stadium can be used by two teams). In a One-To-Many relationship multiple teams/users could use the same stadium, which might become necessary if you have thousands of users and start running out of stadiums.
A JOIN statement would be efficient and sufficient here.
SELECT s.name, t.team_name -- Get the team's and stadium's name
FROM team t -- From the team table
JOIN stadium s -- Join it with the stadium table
ON (t.stadium_id = s.id) -- Join ON the stadium_id
This will return the team name and stadium name of every registered team.
You might need to adjust the query, but you should be able to catch the grasp of it after reading the MySQL reference I linked above.

Pause or manipulate auto increment colum in table

Hi I have a page where a coach would select a team. The selected players gets assigned to an array $player_names. My table, to which I will upload the values in the array, has 3 colums.
selection_id(auto, increment), Fixture_id, and player_names
Now what happens is I upload the player_names to the database but. For each player that gets uploaded the selection_id colums increments. This is wrong because I want all the selected players to hold the same selection_id.
Any advice on how to tackle this problem will be greatly appreciated.
Practical example:
All the players in the image above should have the same selection_id. Only when the next team is selected for a different fixture should it increment by 1
Selection_id
selection_id is based on the team that gets selected on a previous page. Lets say a coach picks his 5 players for a fixture. Now the 5 players gets uploaded to the db. In the team table the selection_id gets assigned to the 5 players selected. What I am trying to do is have the same selection id with each team (5 players) selected for a specific fixture
You have need two tables to manage same selection_id for selected players. selection_id should not auto incremented.
In first table player_id will be auto incremented.
+-------------+-------------+
| player_id | player_name |
+-------------+-------------+
| 1 | Tendai |
| 2 | Andriaan |
| 3 | Janus |
| 4 | Eben |
| 5 | Burger |
+-------------+-------------+
+-------------+--------------+
| player_id | selection_id |
+-------------+--------------+
| 1 | 117 |
| 2 | 117 |
| 3 | 117 |
| 4 | 118 |
| 5 | 118 |
+-------------+--------------+
Using join query you can get selected player for same selection_id

Application specific MySQL table Structure

I have a question about my DB table structure. I want to know if i'm on the right track or if I have missed a good alternative. Here is the case:
To make it easy to read, I haven't pasted the full contents as my question is only about the structure.
2 tables:
1: id (AI), task
2: id, name, task
Table 1 presents dynamic check-boxes which can be altered by an admin panel so the contents would be like this
1 task1
2 task2
5 task5
(3 & 4 are missing cause the administrator deleted those records).
In table number two are the people who should do the tasks from table 1. And the goal is that the tasks wich are not checked will be displayed.
So the contents of table 2 would be:
1 Name1 1,5
2 Name2 1,2
3 Name3 1,2,5
The numbers in table 2 represent the checked boxes from table 1. So with a query i can compare the numbers from table 2 with the id's from table 1 and display the missing ids as "todo".
In my opinion this looks very overdone, and there must be an easier way to create dynamic options which can be compared and stored as a todo.
Suggestions are welcome!
I suggest you to use basic structure for many-to-many relationship:
tasks users user_tasks
+----+-----------+ +----+-------+ +---------+---------+
| id | name | | id | name | | user_id | task_id |
+----+-----------+ +----+-------+ +---------+---------+
| 1 | Buy milk | | 1 | John | | 1 | 2 |
| 2 | Get drunk | | 2 | Tim | | 3 | 2 |
| 3 | Have fun | | 3 | Steve | | 2 | 4 |
| 4 | Go home | +----+-------+ | 3 | 4 |
+----+-----------+ +---------+---------+
And you can fetch unassigned tasks using following query:
SELECT
tasks.*
FROM
tasks
LEFT JOIN
user_tasks
ON (tasks.id = user_tasks.task_id)
WHERE
user_tasks.user_id IS NULL
You also can fetch users who have no assigned tasks:
SELECT
users.*
FROM
users
LEFT JOIN
user_tasks
ON (users.id = user_tasks.user_id)
WHERE
user_tasks.user_id IS NULL
Hope this will help you.

How to store multiple values in single column where use less memory?

I have a table of users where 1 column stores user's "roles".
We can assign multiple roles to particular user.
Then I want to store role IDs in the "roles" column.
But how can I store multiple values into a single column to save memory in a way that is easy to use? For example, storing using a comma-delimited field is not easy and uses memory.
Any ideas?
If a user can have multiple roles, it is probably better to have a user_role table that stores this information. It is normalised, and will be much easier to query.
A table like:
user_id | role
--------+-----------------
1 | Admin
2 | User
2 | Admin
3 | User
3 | Author
Will allow you to query for all users with a particular role, such as SELECT user_id, user.name FROM user_role JOIN user WHERE role='Admin' rather than having to use string parsing to get details out of a column.
Amongst other things this will be faster, as you can index the columns properly and will take marginally more space than any solution that puts multiple values into a single column - which is antithetical to what relational databases are designed for.
The reason this shouldn't be stored is that it is inefficient, for the reason DCoder states on the comment to this answer. To check if a user has a role, every row of the user table will need to be scanned, and then the "roles" column will have to be scanned using string matching - regardless of how this action is exposed, the RMDBS will need to perform string operations to parse the content. These are very expensive operations, and not at all good database design.
If you need to have a single column, I would strongly suggest that you no longer have a technical problem, but a people management one. Adding additional tables to an existing database that is under development, should not be difficult. If this isn't something you are authorised to do, explain to why the extra table is needed to the right person - because munging multiple values into a single column is a bad, bad idea.
You can also use bitwise logic with MySQL. role_id must be in BASE 2 (0, 1, 2, 4, 8, 16, 32...)
role_id | label
--------+-----------------
1 | Admin
2 | User
4 | Author
user_id | name | role
--------+-----------------
1 | John | 1
2 | Steve | 3
3 | Jack | 6
Bitwise logic allows you to select all user roles
SELECT * FROM users WHERE role & 1
-- returns all Admin users
SELECT * FROM users WHERE role & 5
-- returns all users who are admin or Author because 5 = 1 + 4
SELECT * FROM users WHERE role & 6
-- returns all users who are User or Author because 6 = 2 + 4
From your question what I got,
Suppose, you have to table. one is "meal" table and another one is "combo_meal" table. Now I think you want to store multiple meal_id inside one combo_meal_id without separating coma[,]. And you said that it'll make your DB to more standard.
If I not getting wrong from your question then please read carefully my suggestion bellow. It may be help you.
First think is your concept is right. Definitely it'll give you more standard DB.
For this you have to create one more table [ example table: combo_meal_relation ] for referencing those two table data. May be one visible example will clear it.
meal table
+------+--------+-----------+---------+
| id | name | serving | price |
+------+--------+-----------+---------+
| 1 | soup1 | 2 person | 12.50 |
+------+--------+-----------+---------+
| 2 | soup2 | 2 person | 15.50 |
+------+--------+-----------+---------+
| 3 | soup3 | 2 person | 23.00 |
+------+--------+-----------+---------+
| 4 | drink1 | 2 person | 4.50 |
+------+--------+-----------+---------+
| 5 | drink2 | 2 person | 3.50 |
+------+--------+-----------+---------+
| 6 | drink3 | 2 person | 5.50 |
+------+--------+-----------+---------+
| 7 | frui1 | 2 person | 3.00 |
+------+--------+-----------+---------+
| 8 | fruit2 | 2 person | 3.50 |
+------+--------+-----------+---------+
| 9 | fruit3 | 2 person | 4.50 |
+------+--------+-----------+---------+
combo_meal table
+------+--------------+-----------+
| id | combo_name | serving |
+------+--------------+-----------+
| 1 | combo1 | 2 person |
+------+--------------+-----------+
| 2 | combo2 | 2 person |
+------+--------------+-----------+
| 4 | combo3 | 2 person |
+------+--------------+-----------+
combo_meal_relation
+------+--------------+-----------+
| id | combo_meal_id| meal_id |
+------+--------------+-----------+
| 1 | 1 | 1 |
+------+--------------+-----------+
| 2 | 1 | 2 |
+------+--------------+-----------+
| 3 | 1 | 3 |
+------+--------------+-----------+
| 4 | 2 | 4 |
+------+--------------+-----------+
| 5 | 2 | 2 |
+------+--------------+-----------+
| 6 | 2 | 7 |
+------+--------------+-----------+
When you search inside table then it'll generate faster result.
search query:
SELECT m.*
FROM combo_meal cm
JOIN meal m
ON m.id = cm.meal_id
WHERE cm.combo_id = 1
Hopefully you understand :)
You could do something like this
INSERT INTO table (id, roles) VALUES ('', '2,3,4');
Then to find it use FIND_IN_SET
As you might already know, storing multiple values in a cell goes against 1NF form. If youre fine with that, using a json column type is a great way and has good methods to query properly.
SELECT * FROM table_name
WHERE JSON_CONTAINS(column_name, '"value 2"', '$')
Will return any entry with json data like
[
"value",
"value 2",
"value 3"
]
Youre using json, so remember, youre query performance will go down the drain.