struggling with a sql query join - mysql

I am struggling with writing a query join in mysql
I have two table
Challenges
challenge_ID(int) |to_user(int)|from_user(int)|timestamp|gameID=>nullable
Users
iduser(int)|first_name(string)
I want get the first name of to_user and form_user when I have the challengeID
for instance if
Challenges
challenge_ID(int) |to_user(int)|from_user(int)|timestamp|gameID
1 9 10 sometimestamp
Users
iduser(int)|first_name(string)
9 Tom
10 Chris
11 Patrick
I would like to get 'Tom' and 'Chris' for challenge id 1
Thanks for your help.

It may be something like this:
SELECT first_name
FROM Users
WHERE iduser IN (SELECT to_user
FROM challenges
WHERE Challenge_Id = 1
UNION
SELECT from_user
FROM challenges
WHERE Challenge_Id = 1)

this is how you do this
select c.* ,u.first_name as to_name , u2.first_name as from_name
FROM challenges c
join users u on c.to_user = u.id
join users u2 on c.from_user = u2.id
where c.challenge_ID = 1

It looks like you need a UNION and then a JOIN:
SELECT users.first_name
FROM (
SELECT from_user AS usr FROM challenges WHERE challenge_id=1
UNION
SELECT to_user FROM challenges WHERE challenge_id=1
) u INNER JOIN users ON u.usr = users.id_user
UNION will remove duplicates on the subquery, if there are no duplicates you can use UNION ALL which is faster.

You can try this query
SELECT u_to.first_name, u_from.first_name
FROM challenges c
INNER JOIN users u_to ON u_to.iduser = c.to_user
INNER JOIN users u_from ON u_from.iduser = c.from_user
WHERE c.challange_ID = 1

Related

User CASE or subquery?

I have 3 tables: tickets, tickets_users and users. My problem is that in the users table I have 2 types of users: requesters and solvers: type 1 and 2.
I want to select the ticket, requester (if any, can be multiple) and solver (if any, can be multiple).
I'm thinking something in the lines of:
SELECT
t.id, t.description,
(u.id where u.type = 1) AS requester,
(u.id where u.type = 2) AS solver
FROM
tickets t
INNER JOIN
tickets_users tu ON t.id = tu.ticket_id
INNER JOIN
users u ON tu.user_id = u.id
Obviously this does not work.
The tables look like this:
Tickets:
ID Description
1 Description 1
2 Description 2
Tickets_users
ID Ticket_ID User_id Type
1 3 4 1
2 5 8 2
Users
ID Name
1 John
2 Mary
Thanks,
In the meantime I think I found a solution using a sub-query in the join clause, but to me it looks rudimentary:
SELECT
t.id, t.name AS ticket_name, type1.users_id AS requester,
type2.users_id AS solver
FROM
tickets t
INNER JOIN
(SELECT users_id, tickets_id
FROM tickets_users
WHERE TYPE = 1) type1 ON t.id = type1.tickets_id
INNER JOIN
(SELECT users_id, tickets_id
FROM tickets_users
WHERE TYPE = 2) type2 ON t.id = type2.tickets_id
Should be something like this.
SELECT
t.id, t.description, u.id, userType
CASE WHEN u.type = 1 THEN 'requester' ELSE 'solver' END
FROM
tickets t
INNER JOIN tickets_users tu ON t.id = tu.ticket_id
INNER JOIN users u ON tu.user_id = u.id
Please provide sqlfiddle in case above example does not work.
With Joins,
SELECT
t.id, t.description, requesters.id, solvers.id
FROM
tickets t
INNER JOIN tickets_users tu ON t.id = tu.ticket_id
LEFT JOIN users requesters ON (tu.user_id = requesters.id AND requesters.type=1)
LEFT JOIN users solvers ON (tu.user_id = solvers.id AND solvers.type=2)
As you can tell, users table is joined twice (as requesters and as solvers with additional conditions). The reason LEFT JOIN is used is because if there's a record with no requesters or no solvers, INNER JOIN would completely ignore the whole record until it has a requester and a solver.

MYSQL compare values from same columns

Okay I tried to look all over stackoverflow, and the closest solution I found is this:
mysql AND clause on same column multiple times
But I can't use statements and "having" syntax won't work because of group by. There MUST be a simple solution to this.
The 2 tables looks like this (simplified):
users:
uid name
1 person 1
2 person 2
3 person 3
categories:
uid value
1 actor
1 musician
2 actor
3 dancer
4 musician
4 dancer
I want to get the uid of those that are 2 values at the same time. For example, I want to get the UID that is an actor AND a musician. Not just one value, but both of them must be required!
First I tried this:
SELECT users.uid, users.name
FROM
users
LEFT OUTER JOIN categories ON users.uid = categories.uid
WHERE (categories.value = 'actor' AND categories.value = 'musician')
GROUP BY u.uid;
This of course does not work since one row can't have 2 values.
Does anyone know a solution?
You can JOIN to the categories table multiple times to get the result:
SELECT users.uid, users.name
FROM users
INNER JOIN categories c1
ON users.uid = c1.uid
INNER JOIN categories c2
ON users.uid = c2.uid
WHERE c1.value = 'actor'
AND c2.value = 'musician';
See SQL Fiddle with Demo
SELECT users.uid, users.name
FROM users
LEFT JOIN categories ON users.uid = categories.uid
WHERE categories.value in ('actor', 'musician')
GROUP BY u.uid, users.name
having count(distinct categories.value) = 2;
Use a having clause
SELECT u.uid, u.name
FROM users u
LEFT OUTER JOIN categories c ON u.uid = c.uid
WHERE c.value = 'actor' OR c.value = 'musician'
GROUP BY u.uid
having count(distinct c.value) > 1
If you really do not want to use having you could try this:
SELECT uid, name
FROM users
WHERE
uid IN (SELECT uid FROM categories WHERE value='actor')
AND uid IN (SELECT uid FROM categories WHERE value='musician')
But there is really nothing wrong with using HAVING ;)

SELECT all contacts (friends) of a user

I have the following database:
user_id and contact_id from Contacts table are PK and FK to the user_id field in the Users table. How can i select all contacts (or friends) of a specific user including the number of contacts of all contacts of this user. I tried different SELECT queries but either the number of contacts is incorrect or the contact_status is printed wrong. I use COUNT() as a function to print the number of contacts. I use this query but the contact_status is printed wrong:
SELECT COUNT(Contacts.contact_id), Users.user_id, Users.user_name, Users.name, Users.user_picture, Users.mood_message, Users.phone_number, Users.email, Users.country, Users.city, Users.website, Users.birth_date, Users.gender, Users.language, Users.about_me, Users.online_status, Users.privacy, Contacts.contact_status
FROM Contacts JOIN Users ON Contacts.contact_id = Users.user_id
WHERE Users.user_name IN (
SELECT Users.user_name
FROM Users
WHERE Users.user_id IN (
SELECT Contacts.contact_id
FROM Contacts
WHERE Contacts.user_id = 12
)
)
GROUP BY Users.user_name;
Users Table:
user_id, user_name, ...
12 John ...
13 Matt ...
14 Jack ...
Contacts Table:
user_id, contact_status, contact_id
12 1 13
13 1 12
12 2 14
If i want to print all Contacts of John the result should consist:
COUNT(Contacts.contacts_id), Users.user_name, Users. ... , Contacts.contact_status
1 Matt ... 1
0 Jack ... 2
The above query prints 1, 1 as a contact_status instead of 1, 2.
Can you help me with this query? Thanks in advance.
If I understood what's your goal, this should work:
SELECT c.contact_status, cc.contactCount, u.*
FROM Contacts c JOIN Users u ON (c.contact_id = u.user_id)
JOIN (
SELECT user_id, COUNT(1) contactCount FROM Contacts
GROUP BY user_id
) cc ON (c.user_id = cc.user_id)
WHERE c.user_id = 12
I hope I understand ur requirements, but its much simpler to use a subquery, like so:
SELECT
u.* -- Whatever fields you need
,(
select count(*) from Contacts c
where c.contactid = co.userid -- refers to outer record
) as contact_count
FROM
Users u Inner Join Contacts co
on co.UserId = u.UserId
WHERE
U.UserId = 12

SQL - Get two users' names

I'm trying to get names of users from a voting table, I can't quite figure out how to get both the voter's name and the votee's name.
Simplified Votes Table
ID voteeID voterID
1 1 2
2 1 3
3 1 4
4 2 1
5 2 3
6 2 4
Simplified User Info Table
ID username
1 Bob
2 Sam
3 Ed
4 Mark
Where I'm at:
SELECT votes.voteeID, votes.voterID, userinfo.username
FROM votes
JOIN ???
I was playing around with the join, but I'm kind of stuck. If I join on the votee's id to the userinfo id, how would I also get the voter's name or vice versa?
Database: MySQL 5
Any help or even a hint would be wonderful, thanks in advance.
try this one,
SELECT b.`username` as Votee_Name,
c.`username` as Voter_Name
FROM Votes a
INNER JOIN UserInfo b
ON a.voteeID = b.Id
INNER JOIN UserInfo c
on a.voterID = c.id
SQLFiddle Demo
How about something like
SELECT v.ID,
v.voteeID,
u1.username Votee,
v.voterID,
u2.username Voter
FROM Votes v INNER JOIN
User u1 ON v.voteeID = u1.ID INNER JOIN
User u2 ON v.voterID = u2.ID
You need to take INNER JOIN twice to get usernames for both votee and voter:
SELECT a.voteeID, a.voterID,
b.username AS votee_name, c.username AS voter_name
FROM votes a
INNER JOIN userinfo b
ON a.voteeID = b.ID
INNER JOIN userinfo c
ON a.voterID = c.ID;
SELECT V.ID as ID B.username as Votee_Name, C.username as Voter_Name
FROM Votes V
INNER JOIN UserInfo B ON V.voteeID = B.Id
INNER JOIN UserInfo C on V.voterID = C.id;

Collecting data from 3 tables into 1 query

I have three different tables in my MySQL database.
table users: (id, score, name)
table teams: (id, title)
table team_Members: (team_id, user_id)
What I would like to do is to have 1 query that finds every team ID a given user ID is member of, along with the following information:
total number of members in that team
the name of the team
users rank within the team (based on score)
EDIT:
Desired output should look like this;
TITLE (of the group) NUM_MEMBERS RANK
------------------------------------------------
Foo bar team 5 2
Another great group 34 17
.
.
.
The query should be based on the users ID.
Help is greatly appreciated
I think this query should get what you ask for
select t.id, t.title, count(m.user_id) members, (
select count(1)
from users u3
inner join team_Members m3 on u3.id = m3.user_id
and m3.team_id = t.id and u3.score > (
select score from users where name = 'Johan'
)
) + 1 score
from teams t
inner join team_Members m on t.id = m.team_id
where t.id in (
select team_id
from team_Members m2
inner join users u2 on m2.user_id = u2.id
where u2.name = 'Johan'
)
group by t.id, t.title
To collect you just need use JOIN
SELECT
u.*, t.*, tm.*
FROM
users u
JOIN
team_Members tm ON u.id = tm.user_id
JOIN
teams t ON t.id = tm.team_id;
To get total of number of that team use COUNT with some group key
Some like that
SELECT
COUNT(t.id), u.*, t.*, tm.*
FROM
users u
JOIN
team_Members tm ON u.id = tm.user_id
JOIN
teams t ON t.id = tm.team_id GROUP BY t.id;
And to rank just:
SELECT
COUNT(t.id) as number_of_members, u.*, t.*, tm.*
FROM
users u
JOIN
team_Members tm ON u.id = tm.user_id
JOIN
teams t ON t.id = tm.team_id
GROUP BY t.id
ORDER BY u.score;