MySQL JOIN to show required output - mysql

Is there a way I can select all columns from two tables in MySQL, but only show the data in the end column if a match is found in both tables?
For example…
Main table (contacts)
id| token | Name
------------------
1 | ABC | Test person 1
2 | DEF | Test person 2
3 | GHI | Test person 3
Subscriptions table (subscribed)
id| contact_token
-------------------
1 | ABC
Desired output
id| token | Name | contact_token
------------------------------------------
1 | ABC | Test person 1 | ABC
2 | DEF | Test person 2 |
3 | GHI | Test person 3 |
The contents of contact_token is show (ABC) because it appears in both tables.
Thanks

You should consider storing the subscription data in the main contacts table, unless you can have multiple subscriptions per user. If the latter is the case, then you have to consider if you want to see the subscription tokens within one line in the output or in multiple lines.
The basic query is simple, you need to left join the subscribed table to the contacts:
select contacts.id, token, name, contact_token
from contacts left join subscribed
on contacts.id=subscribed.id

Yes. This is what a LEFT JOIN is for:
You select all records from table contacts and you do a left join on the subscribed one.
SELECT subscribed.id,token,name,contact_token
FROM contacts LEFT JOIN subscribed
ON contacts.id = subscribed.id;
For the records that are only in the first table you will get NULL in the last column.

Related

Select two values from two different tables

I have two tables, they look like this:
Table 1
==========================
id_tab1 | worker | number
==========================
1 | Adam | 123123
Table 2
==========================
id_tab2 | worker | number
==========================
1 | Adam | 123456
They both don't have anything in common. Sometimes worker might be in both of them and I want to count every row from both tables and show them like:
===============================================
worker | count_numbers_tab1 | count_numbers_tab2
===============================================
Adam | 1 | 1
I tried with INNER JOIN but it shows weird numbers.
EDIT 1:
As with Abhilekh answer I ended up with following query(real example):
SELECT druga_klasa.pracownik, COUNT(druga_klasa.numer_zlecenia), COUNT(zlewy_zlomy.numer_zlecenia) FROM druga_klasa
FULL JOIN zlewy_zlomy on druga_klasa.pracownik=zlewy_zlomy.pracownik
GROUP BY pracownik;
and thats how real tables looks like
and I've got an error saying
Unknown column druga_klasa.pracownik in field list.
What do you mean by they both don't have anything in common?
SELECT table1.worker, COUNT(table1.number), COUNT(table2.number) FROM table1
INNER JOIN table 2 on table1.worker=table2.worker
GROUP BY worker;
But this will only work if the column worker is common to both.

join two tables in mysql and get records

I have two tables "contacts" and "users". Users table storing data with "," separated. Need to distinct data in "Contacts" column from "Contacts" table. And need to join with "Users" table, and get the records.
Contacts Table
--------------------------
id | user_Id | contats
--------------------------
1 | 2147483647 | 90123456789,90123456789,90123456789,90123456789
2 | 2147483647 | 90123456789,90123456789,90123456789,90123456789
3 | 919444894154 | 90123456789,90123456789,90123456789,90123456789
Users Table
-----------------------------
id | username | email | phone
-----------------------------
1 | bhavan | bhavanram93#gmail.com | 90123456789
2 | bhavan | bhavanram93#gmail.com | 90123456789
3 | prince | prince#gmail.com | 1234567980
4 | bhavan | bhavanram93#gmail.com | 90123456789
5 | hello | hello#gmail.com | 1234567890
6 | bhavan | bhavanram93#gmail.com | 90123456789
Your table Contacts shouldn't be constructed this way.
Since you want 1 Users table containing all the data about a user, and 1 Contacts table containing links between different users, you'd rather do this kind of table structure :
Contacts table
id | user_id | contact_id
-------------------------
1 | 1 | 2
2 | 1 | 3
3 | 2 | 3
That'll allow you to do something like :
SELECT *
FROM Users
JOIN Contacts ON (Users.id = Contacts.contact_id)
WHERE Contacts.user_id = 1
Which will return all the data of the contacts of the user 1.
Your current structure is a huge ongoing mess, it's the opposite of being flexible.
You should restructure your db to a normalized format as Steve suggest.
But if you cant:
SELECT *
FROM Users
JOIN Contacts
ON CONCAT(',', Contacts.contacts, ',') like
CONCAT('%,', Users.phone, ',%')
WHERE Contacts.user_id = 1
the idea is you convert your contacts to
, <numbers> ,
,90123456789,90123456789,90123456789,90123456789,
and try to match with
%,90123456789,%
Note this approach cant use any index so will have bad performance with many
rows. if you are in the order of 1k-10k rows may be ok. More than that you need consider restructure your db.

SQL Tables of the Same Column to Join

I currently have a problem as how to fetch data separately, in the same table, but of different conditions.
To better illustrate, take the example below as my tables.
disputes table
id | user_to | bidder_id
1 | 1 | 2
users table
user_id | user_name
1 | userone
2 | usertwo
I'd like to have an output that combines both like this:
final output table
id | user_to | bidder_id | user_to_name | bidder_id_name
1 | 1 | 2 | userone | usertwo
I do not know how to really put it into words but I hope the illustration helps :
It seeks for the "user_to" and "bidder_id" rows, associates them to the "user_id" in the users table, where it creates two new columns that associates the "user_id" and "bidder_id" to the respective ids in the users table and fetches the user_name in the id given in the field.
LEFT JOIN is your friend. see the exsample:
sample
SELECT d.*,
utn.user_name AS user_to_name ,
bin.user_name AS bidder_id_name
FROM disputes d
LEFT JOIN users utn on utn.user_id = d.user_to
LEFT JOIN users bin on bin.user_id = d.bidder_id;

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.

Join on piped column data

I have to work with a MySQL database where some columns have different IDs saved in one column, separated by a piped character. For example:
Users table:
id | username | groups
1 | user1 | 1|2|3|5
The group IDs correspond to groups. It shows in what groups a user is placed in. So there is also a Groups table:
Groups table:
id | groupname
1 | group1
2 | group2
3 | group3
4 | group4
5 | group5
What i'd like to do is select a user and then select all the groupnames that this user is placed in, something like a JOIN. For user1 this is all groups except group4.
This would obviously be easier if the groups were saved in another table called user_groups, which could look like this:
user_groups table:
fk_user_id | fk_group_id
1 | 1
1 | 2
1 | 3
1 | 5
But, unfortunately i cannot change the database schema since an entire system is already based in this.
I'd like to know if there is a smart way of getting all the groupnames when selecting a user in a single query. For example a result could look something like this:
id | username | groups | groupnames
1 | user1 | 1|2|3|5 | group1|group2|group3|group5
Is it possible somehow to do something like this in one query with MySQL?
In MySQL, you can use find_in_set() for this type of join:
select *
from user u join
groups g
on find_in_set(g.groupname, u.groups) > 0;
In MySQL, or other databases, you can use like as well:
select *
from user u join
groups g
on concat('|', g.groupname, '|') like concat('%|', u.groups, '|%');