SQL query to combine columns from 3 different tables? - mysql

So basically I have 3 differnet tables named member, phone_message and pc_message each with the following columns:
member = (id, cell_num)
phone_message = (phone_num, content, received_at)
pc_message = (member_id, content, sent_at)
What i'm trying to do here is to list all the messages including both phone and pc that are received or sent for each member. To do that i need to combine those tables into one using SQL queries like JOIN and UNION. Any help?

You can try below query, I have used inner join so that messages only sent by matching members will be diplayed.
In addition to that, I have added one extra column as device which will identify whether the message is sent on phone or pc.
select m.id as memberId, m.cell_num as phoneNumber, p.content as Message, p.received_at as recieveDate,'Phone' as device from member m
inner join phone_message p on m.cell_num = p.phone_num
union
select m.id as memberId, m.cell_num as phoneNumber, pc.content as Message, pc.sent_at as recieveDate,'PC' as device from member m
inner join pc_message pc on m.id = pc.member_id

Try this;
select m.id as memberId, m.cell_num as phoneNumber, p.content, p.received_at as recieveDate from member m
inner join phone_message p on m.cell_num = p.phone_num
union
select m.id as memberId, m.cell_num as phoneNumber, pc.content, pc.sent_at as recieveDate from member m
inner join pc_message pc on m.id = pc.member_id

Related

Inner Join SQL table multiple times for the same table

I have two tables (msg and users). I am trying to join these two tables together and print out the first and last name of the sender and the recipient as well as all of the message content if the message is marked as flag. I keep getting errors though, and have not found a good way to do this yet.
Pictures of tables for reference: https://imgur.com/a/wYuptfR
SQL query I'm using right now:
SELECT msg.*, users.uuid AS users.ruuid, users.uuid AS users.suuid, users.firstName, users.lastName
FROM msg
INNER JOIN users ON users.ruuid = msg.recipient
AND INNER JOIN users ON users.suuid = msg.sender
WHERE msg.flag = 0
You can query the same table several times if you use different aliases. Also, note you shouldn't have an and between the two join clauses:
SELECT msg.*,
r.uuid AS ruuid, r.firstName AS rfirstname, r.lastName AS rlastname,
s.uuid AS suuid, s.firstName AS sfirstname, s.lastName AS slastname
FROM msg
INNER JOIN users r ON r.uuid = msg.recipient
INNER JOIN users s ON s.uuid = msg.sender
WHERE msg.flag = 0
Try This
SELECT msg.*, u.uuid , u.firstName, u.lastName, s.uuid , s.firstName, s.lastName
FROM msg
INNER JOIN users u ON u.uuid = msg.recipient
INNER JOIN users s ON s.uuid = msg.sender
WHERE msg.flag = 0

Grouping by Count(*) following multiple join operations

Trying to figure out what I thought was a simple query-
I have the following tables with schemas as follows.
models(id: int, first_name: string, last_name: string)
painters(id: int, first_name: string, last_name:string)
portraits_painters(painter_id: int, portrait_id: int)
roles(model_id: int, portrait_id: int)
I am trying to satisfy this query: The first name, last name, and count
for painters who have been the model for their own painting- i.e. where the count column for a first and last name is the number of self portraits the painter has done (both the painter and model). (Safe to assume equal first names and last names mean the same individual).
If a painter has no self portraits they should not even be included in the final output.
SELECT
models.first_name,
models.last_name,
COUNT(portraits_painters.portrait_id)
FROM models
RIGHT JOIN painters
ON models.first_name = painters.first_name
AND models.last_name = painters.last_name
RIGHT JOIN portraits_painters
ON portraits_painters.painter_id = painters.id
RIGHT JOIN roles
ON roles.portrait_id = portraits_painters.portrait_id
GROUP BY portraits_painters.portrait_id;
I essentially tried to narrow the table down to rows where names matched, followed by instances where the painter ids matched and the portrait id's matched, but evidently there's something incorrect in how I am joining tables.
I'm also getting errors in regards to the GROUP BY portion, so not sure if there's a better way to approach it? Perhaps aliasing?
You can get the names of the models and painters using:
select m.first_name, m.last_name, p.first_name, p.last_name
from roles r join
portraits_painters pp
on pp.portrait_id = r.portrait_id join
painters p
on p.id = pp.painter_id join
models m
on m.id = r.model_id;
The rest is just a where and group by:
select p.first_name, p.last_name, count(*)
from roles r join
portraits_painters pp
on pp.portrait_id = r.portrait_id join
painters p
on p.id = pp.painter_id join
models m
on m.id = r.model_id
where m.first_name = p.first_name and m.last_name = p.last_name
group by p.first_name, p.last_name;
I am not sure what thinking leads to outer joins or exists clauses.
Get painter infos for all portraits:
SELECT p.first_name, p.last_name, pp.portrait_id
FROM portraits_painters AS pp
JOIN painters AS p
ON pp.painter_id = p.id
Get model infos for all portraits:
SELECT m.first_name, m.last_name, pp.portrait_id
FROM roles AS r
JOIN models AS m ON m.id = r.model_id
JOIN portraits_painters AS pp ON pp.portrait_id = r.portrait_id
Combine these two tables on the same first_name and last_name. Now you get both painter infos and model infos for every portrait. Just group the records by first_name and last_name, and COUNT for each group, you get what you want.
So, the final query would be:
SELECT a.first_name, a.last_name, COUNT(a.portrait_id)
FROM
(
SELECT p.first_name, p.last_name, pp.portrait_id
FROM portraits_painters AS pp
JOIN painters AS p
ON pp.painter_id = p.id
) AS a
JOIN
(
SELECT m.first_name, m.last_name, pp.portrait_id
FROM roles AS r
JOIN models AS m ON m.id = r.model_id
JOIN portraits_painters AS pp ON pp.portrait_id = r.portrait_id
) AS b
ON a.first_name = b.first_name AND a.last_name = b.last_name
GROUP BY a.first_name, a.last_name;

Reference outside inner join query

I have the following query for a basic messaging system. It shows the messages that you've sent. However, it is showing the first_name and second_name for the account referenced by sender_id. Instead I want it to output the name columns referenced by receiver_id
ie) SELECT first_name, second_name WHERE accounts.account_id = messages.receiver_id
Do I need to write a seperate query for this or can I make this one output it in a single query? I've been thinking quite hard about this problem!
SELECT first_name, second_name, message_id, title, body, seen, urgent, type, messages.timestamp
FROM messages
INNER JOIN accounts
ON messages.sender_id=accounts.account_id
WHERE sender_id = ?
You can do this with two joins:
SELECT s.first_name as sender_first, s.second_name as sender_last,
r.first_name as rec_first, r.second_name as rec_last,
m.message_id, m.title, m.body, m.seen, m.urgent, m.type, m.timestamp
FROM messages m inner join
accounts s
ON m.sender_id = s.account_id inner join
accounts r
on m.receiver_id = r.account_id
WHERE m.sender_id = ?

Complex MySQL query with multiple select statements

I have three tables in Mysql that are link together:
Profile (ID, Name, Stuff..)
Contact(ID, ProfileID,desc,Ord)
Address(ID,ProfileID, desc, Ord)
Now I need to select all profile from the profile table, with the “desc” field from Contact and Address where Ord = 1. (this is for a search function where in a table I’ll display the name, main contact info and main Address of a client.
I can currently do this with three separate SQL request:
SELECT Name, ID FROM Profile WHERE name=”bla”
Then in a foreach loop, I’ll run the other two requests:
SELECT ProfileID, desc FROM Contact WHERE ProfileID=MyProfileID AND Ord=1
SELECT ProfileID, desc FROM Address WHERE ProfileID=MyProfileID AND Ord=1
I know you can do multiple SELECT in one query, is there a way I could group all three SELECT into one query?
You should be able to JOIN the tables on the profile.id and the profileid in the other tables.
If you are sure the profileid exists in all three tables, then you can use an INNER JOIN. The INNER JOIN returns matching rows in all of the tables:
select p.id,
p.name,
c.desc ContactDesc,
a.desc AddressDesc
from profile p
inner join contact c
on p.id = c.profileid
inner join address a
on p.id = a.profileid
where p.name = 'bla'
and c.ord = 1
and a.ord = 1
If you are not sure that you will have matching rows, then you can use a LEFT JOIN:
select p.id,
p.name,
c.desc ContactDesc,
a.desc AddressDesc
from profile p
left join contact c
on p.id = c.profileid
and c.ord = 1
left join address a
on p.id = a.profileid
and a.ord = 1
where p.name = 'bla'
If you need help learning JOIN syntax, here is a great visual explanation of joins
This query below only selects column when an ID from Profile table has atleast one match on tables: Contact and Address. If one or both of them are nullable, use LEFT JOIN instead of INNER JOIN because LEFT JOIN displays all records from the Left-hand side table regardless if it has a match on other tables or not.
SELECT a.*,
b.desc as BDESC,
c.desc as CDESC
FROM Profile a
INNER JOIN Contact b
ON a.ID = b.ProfileID
INNER JOIN Address c
ON a.ID = c.ProfileID
WHERE b.ORD = 1 AND
c.ORD = 1 AND
a.Name = 'nameHERE'
The LEFT JOIN version:
SELECT a.*,
b.desc as BDESC,
c.desc as CDESC
FROM Profile a
INNER JOIN Contact b
ON a.ID = b.ProfileID AND b.ORD = 1
INNER JOIN Address c
ON a.ID = c.ProfileID AND c.ORD = 1
WHERE a.Name = 'nameHERE'
To further gain more knowledge about joins, kindly visit the link below:
Visual Representation of SQL Joins
i have created working demo as your requirement :
The query bellow will retrieve all matching records from the database.its retrieving profile id,name stufff and description of contact tables
select p.id,p.name,p.stauff,c.descr,a.descr from profile as p
inner join contact as c on c.profileid=p.id
inner join address as a on a.profileid=p.id
where p.name="bla" and c.ord=1 and a.ord=1

Joining two tables twice in MySQL. Possible or Not???

The table structures for the tables users,messages are like bellow,
Users - ID, Name
Messages - ID, Sender, Receiver, Message
I want to join two tables twice like joining the messages.sender with users.id and messages.receiver with users.id.
Is it possible to get the result with sender's id, sender's name, receiver's id, receiver's name, message...(etc) in a single query???...
Yes, you can join the tables as many times as needed.
SELECT
sender.ID AS `sender_id`,
sender.Name AS `sender_name`,
receiver.ID AS `receiver_id`,
receiver.Name AS `receiver_name`,
Messages.Message
FROM
Messages
INNER JOIN
Users AS sender
ON
sender.ID = Messages.Sender
INNER JOIN
Users AS receiver
ON
receiver.ID = Messages.Receiver
Yes you can do it by naming an inner join:
select id, s.Name, r.Name from Messages
inner join users as s on (message.sender = s.id)
inner join users as r on (merssage.receiver = r.id)