How to select multiple values with join in sql - mysql

I have a database called "forum" with the tables:
"users", containing: user_id, username, password
"posts", containing: post_id, user_id (FK from "users"), type, title, content
"comments", containing: comment_id, user_id (FK from "users"), post_id (FK from posts"), content
At the moment, i'm using the query:
SELECT *
FROM forum.comments
JOIN forum.posts ON (comments.post_id = posts.post_id)
JOIN forum.users ON (posts.user_id= users.user_id)
With this query i can only display the username of the person who made the post, not the comment. How can i change this to show who made the comment, AND who made the post in the same query?
(If someething in the query is written wrong, it's just cause i had to translate it from another language, the query does return results).

You can join the table more than once if you alias the tables:
SELECT * FROM forum.comments AS c
JOIN forum.posts AS p ON (comments.post_id = posts.post_id)
JOIN forum.users AS u1 ON (posts.user_id = users.user_id)
JOIN forum.users AS u2 ON (comments.user_id = users.user_id)
When you do that, you can reference columns from the table by doing something like SELECT u1.username, u2.username ....

Related

create mysql view for many-to-many relationship

MYSQL script to create a MYSQL view Table to show use id , email , and the assigned role/s name/s through many-to-many relationship
I wrote the script and joined tables to create the view table but it shows role name for the first record only the other users has null although they have roles!.
Tables
users (id, email)
roles (id, name)
role_users (id, user_id, role_id)
My script
DROP VIEW IF EXISTS users_view;
CREATE VIEW users_view AS
SELECT users.id AS user_id, users.email, roles_names.role_name
FROM users
LEFT JOIN(
SELECT role_users.user_id AS roles_user_id,
role_users.role_id AS roles_role_id
FROM role_users
) AS user_roles ON (roles_user_id = users.id)
LEFT JOIN(
SELECT roles.id AS roleid, roles.name AS role_name
FROM roles
) AS roles_names ON (roleid = user_roles.roles_user_id)
view created success but it shows the role name for the first user only , other users has role_name value of null although they have records at role_users table
SELECT u.id AS user_id, u.email, IFNULL(u_roles.role_name,'') as role_name
FROM users u
LEFT JOIN
(SELECT GROUP_CONCAT(DISTINCT r.name SEPARATOR ',') as role_name, ur.user_id
FROM roles r INNER JOIN user_roles ur
ON r.id = ur.role_id
GROUP BY ur.user_id) u_roles
ON u.id = u_roles.user_id
Since role users will be having all only roles from roles table, inner join on roles and user_roles will be fine.
By this query all records which are having an entry in user_roles table will show role name and rest of the users will be having null as role name (adding IFNULL check to make null values an empty string)

Mysql: count and group unique emails in associated tables by polymorphic join

The relevant part of my schema (Mysql 5.6.24) is thus:
table: training_event_invitees
registered (tinyint)
invitee_id (id)
invitee_type (varchar)
table: users
id (integer)
email (varchar)
school_id (integer)
table: contacts
id (integer)
email (varchar)
school_id (integer)
table: schools
id (integer)
email (varchar)
I want to try to do the following: get all the training_event_invitees that have registered set to 1, get the associated school, user and contact records, and then group them by school_id, and return the school id and the count of unique email addresses from that school.
training_event_invitees has a two-column foreign key, using invitee_id and invitee_type: invitee_type would be either "School", "User" or "Contact", and references the id field from the corresponding table.
So, algorithmically, it's something like
- get all the registered training_event_invitees
- get all of the associated user, contact and school records
- group these by users.school_id, contacts.school_id or schools.id
- count the number of distinct emails in each group
So, it should return an array like
[
[1234, 6],
[3407, 2]
]
where 1234 and 3407 are values of school_id and 6 and 2 are the count of distinct emails.
I can break this down into a few steps, but there must be a one-hit way to do it. Can anyone help?
One method is to combine the two tables using left join, and then doing the aggregation:
select coalesce(u.school_id, c.school_id) as school_id,
count(distinct coalesce(u.email, c.email)) as num_emails
from training_event_invitees tei left join
users u
on u.id = tei.invitee_id and tei.invitee_type = 'user' left join
contacts c
on c.id = tei.invitee_id and tei.invitee_type = 'contact'
where tei.registered = 1
group by coalesce(u.school_id, c.school_id);
EDIT:
To include the school, follow the same logic:
select coalesce(u.school_id, c.school_id, s.id) as school_id,
count(distinct coalesce(u.email, c.email, s.email)) as num_emails
from training_event_invitees tei left join
users u
on u.id = tei.invitee_id and tei.invitee_type = 'user' left join
contacts c
on c.id = tei.invitee_id and tei.invitee_type = 'contact' left join
schools s
on s.id = tei.invitee_id and tei.invitee_type = 'school'
where tei.registered = 1
group by coalesce(u.school_id, c.school_id, s.id);

Using multiple columns in a join on same field in second table

Consider the following :
**Table 1 - record**
id (int primary key),
addedby (int),
editedby (int)
**Table 2 - users**
id (int primary),
name (shorttext)
**Sample Records**
record
0 1 1
1 1 2
users
1 user1
2 user2
What I need is so do a join to to be able to show the following :
record.id, users.addedby, users.editedby
I tried, amongst others, the following :
select record.id, users.name, users.name from record left join users on record.addedby=users.id left join users on record.editedby=users.id
However, it's not even logical that that will work, so I am a bit stuck.
Any help would be much appreciated. Thank you.
Just join the same table twice. Nothing unusual. You just have to alias the tables to be able to refer to them independently.
select r.id, u1.name added, u2.name editor
from record r
inner join user u1
on r.addedby = u1.id
inner join user u2
on r.editedby = u2.id
heres a demo
Use aliasses:
select record.id, users1.name, users2.name
from record
left join users users1 on record.addedby=users1.id
left join users users2 on record.editedby=users2.id

basic join on mysql

I am having a hard time understanding joins on mySQL, and I cannot find any similar example to work with.
Suppose I have two tables: users and users_info.
in users I have id, email and password fields while, in users_info I have all their information, like name, surname, street, etc.
so, if I am getting a user like this:
SELECT * FROM users WHERE id = 43
and their information like this:
SELECT * FROM users_info WHERE id = 43
I will basically get 2 results, and 2 tables.
I understand now that I need to use join so that they are all together, but I just can't figure out out.
Any help?
It seems like both tables users and user_info are related with each others by the column id therefore you need to join them using this column like this:
SELECT
u.id,
u.email,
u.password,
i.name,
i.surname,
i.street
FROM users AS u
INNER JOIN user_info AS i ON u.id = i.id;
This will only select the fields id, email, ... etc. However, if you want to select all the columns from both the tables use SELECT *:
SELECT *
FROM users AS u
INNER JOIN user_info AS i ON u.id = i.id;
If you want to input the id and get all of these data for a specific user, add a WHERE clause at the end of the query:
SELECT *
FROM users AS u
INNER JOIN user_info AS i ON u.id = i.id
WHERE u.id = 43;
For more information about JOIN kindly see the following:
Join (SQL)From Wikipedia.
Visual Representation of SQL Joins.
Another Visual Explanation of SQL Joins.
Here's an example
SELECT * FROM users u
INNER JOIN users_info i
ON u.id=i.id
this means, you are joining users table and users_info table
for example
users
id name
---- -------
1 abc
2 xyz
users_info
id email
--- ------
1 abc#aaa.com
2 xyz#aaa.com
the query will return
id name email
--- ----- -------
1 abc abc#aaa.com
2 xyz xyz#aaa.com
Here's a nice tutorial
You can also do:
SELECT users.*, users_info.*
FROM users, users_info
WHERE users.id = users_info.id AND users.id = 43;
This means:
"Get me all the columns from the users table, all the columns from the users_info table for the lines where the id column of users and the id column of users_info correspond to each other"

A complex data not sure how to explain it

Hi I have a table called Users and a table called friends, friends table have two data types UserID and FriendID, (foreign key of both data types to primary key of the Users table),
I need to give an ID and find a list of that persons friends'name, I am not sure if I have designed the tables wrongly or I should rewrite the query.
my query is as following, (so far it just shows the details of first matched person)
SELECT Users.Name
FROM Users
WHERE Users.ID = SELECT Friends.UserID
FROM Friends,Users
WHERE Users.ID = (Select Users.ID
From Users
WHERE Users.Username = 'John')
Try this:
SELECT Users.Name FROM Users WHERE Users.ID IN -- Get names that belongt to ID's
(SELECT FriendID FROM Friends WHERE UserID = -- All ID's of the Friends of
(SELECT UserID FROM Users WHERE Name = 'John')) -- Johns ID
I've solved it by changing the first = to IN
is this you want to achieve ??
User
UserID (PK)
Name
Friend
FriendID (PK)
UserID (FK)
select User.Name from User u join Friend f on f.UserID = u.UserID where Name = 'John'