User CASE or subquery? - mysql

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.

Related

How to select more rows based on column id of first select

I have 2 select statements. One returns 2 rows and the other must return more rows. I want to select all of the rows in one single query and not use a UNION because I will not be able to use the same column id with UNION.
My query is this
SELECT SUB.name FROM (SELECT U1.id ,U1.name, UOM.organization_id AS ORGID FROM #_users AS U1
JOIN #_user_organization_map AS UOM ON U1.id = UOM.user_id
JOIN #_rsdirectory_entries AS RSE ON UOM.organization_id = RSE.id
JOIN #_rsmembership_membership_subscribers AS RMS ON U1.id = RMS.user_id
WHERE RMS.membership_id = 66 AND UOM.organization_id = 301) AS SUB
JOIN #_users AS U ON SUB.id = U.id
JOIN #_user_organization_map AS UOM1 ON SUB.id = UOM1.user_id
JOIN #_rsdirectory_entries AS RSE1 ON UOM1.organization_id = RSE1.id
JOIN #_rsmembership_membership_subscribers AS RMS1 ON SUB.id = RMS1.user_id
WHERE UOM1.organization_id = SUB.ORGID;
What i'm trying to do is get all users belonging to a specific membership but not all users carry the membership_id value in their details in the database, only the CEO of the organization.
So, the nested SELECT should get the CEO's name to whom the subscription belongs (hence the membership_id) and then in the outer SELECT I want to get all of the employees under the same organization, by organization ID.
The result I get is the CEO's name twice but I should get the CEO's name and then all of the employees' names.
The subquery is only returning the CEO's information. The information about the employees is in the U table that you join with it.
But you can't join on U.id = SUB.id, because that just restricts U to the CEO's row. You want to get all the users in the same organization as the CEO.
I think this will do it. The last three joins get the organization ID of the CEO
SELECT U.name
FROM #_users AS U1
JOIN #_user_organization_map AS UOM1 ON1 U.id = UOM1.user_id
JOIN #_user_organization_map AS UOM ON UOM1.id = UOM.id
JOIN #_rsdirectory_entries AS RSE ON UOM.organization_id = RSE.id
JOIN #_rsmembership_membership_subscribers AS RMS ON U1.id = RMS.user_id
WHERE RMS.membership_id = 66 AND UOM.organization_id = 301

Field list in ambiguous in join with 4 tables

Very confused why this is happening since I'm naming the specific tables as es and sub that it's complaining about (and I think that's how you fix that particular issue).
I've got:
users submissions_comments email_settings submissions tables
This query gives me what I want, but I now want to join this on my email_settings and submissions table which both have a user_id.
SELECT user_id,
submission_id,
comment,
users.*,
FROM submissions_comments
INNER JOIN
(SELECT submissions_comments.parent_id
FROM submissions_comments
WHERE id = 224) x ON submissions_comments.id = x.parent_id
LEFT JOIN users ON submissions_comments.user_id = users.id
Output:
user_id: 35
submission_id: 12
comment: fdasadfsdadfs
id: 35
email: bobcobb#gmail.com
username: bobcobb
name: Robert Cobb
about:
created: 2014-03-21 20:24:57
last_login: 2014-07-06 23:21:43
public_profile: 1
queued_photo: 0
But if I try to join on another table (which has a reference to a user_id) I get Column 'user_id' in field list is ambiguous
SELECT user_id,
submission_id,
comment,
users.*,
es.*,
sub.*
FROM submissions_comments
INNER JOIN
(SELECT submissions_comments.parent_id
FROM submissions_comments
WHERE id = 224) x ON submissions_comments.id = x.parent_id
LEFT JOIN users ON submissions_comments.user_id = users.id
LEFT JOIN submissions sub ON x.parent_id = sub.user_id
LEFT JOIN email_settings es ON x.parent_id = es.user_id;
As you can tell I'm joining all of these on the user_id returned from the inner select (e.g. x.parent_id).
You have to add the alias to the column name:
SELECT sub.user_id,...
SELECT submissions_comments.user_id,
submissions_comments.submission_id,
submissions_comments.comment,
users.*,
es.*,
sub.*
FROM submissions_comments
INNER JOIN
(SELECT submissions_comments.parent_id
FROM submissions_comments
WHERE id = 224) x ON submissions_comments.id = x.parent_id
LEFT JOIN users ON submissions_comments.user_id = users.id
LEFT JOIN submissions sub ON x.parent_id = sub.user_id
LEFT JOIN email_settings es ON x.parent_id = es.user_id;
you need to define which user_id you are referring on the select part as well.

How to get another table field information

I have three tables, user/team/user_team(many-to-many)
user
-----------
id name
1 Tom
2 Jerry
3 John
team
------------
id name
1 t1
2 t2
3 t3
user_team
---------------------
userid teamid isdeleted
1 t1 0 <----(0 means not deleted record, which can be searched out)
2 t2 1 <----(1 means deleted record, which can not be searched out)
I want to get all team records information with associated user information like below
--------------
tid tname username
1 t1 Tom
2 t2
3 t3
Can you tell me how to write the sql statement?
Sorry for my mistake. I've updated my question by adding one more record t3 in team table.
try this:
Select a.id as tid
a.name as tname
b.name as username
from team a
LEFT JOIN user_team c on a.name = c.teamid and c.isdeleted = 0
LEFT JOIN user b on b.id = c.userid
I think what you're looking for is a simple OUTER JOIN:
select t.id as tid,
t.name as tname,
u.name as username
from team t
left join user_team ut on t.id = ut.teamid and ut.isdeleted = 0
left join user u on ut.userid = u.id
A Visual Explanation of SQL Joins
Try this:
SELECT t.id tid, t.name tname, GROUP_CONCAT(u.name) usernames
FROM user_team ut
LEFT OUTER JOIN team t ON ut.teamid = t.id
LEFT OUTER JOIN user u ON ut.userid = u.id
GROUP BY t.id;
To include the flag that can be searched out try this (just include a condition for flag):
SELECT t.id tid, t.name tname, GROUP_CONCAT(u.name) usernames
FROM user_team ut
LEFT OUTER JOIN team t ON ut.teamid = t.id
LEFT OUTER JOIN user u ON ut.userid = u.id
AND ut.isdeleted = 1 --this will add a condition for deleted teams
GROUP BY t.id;
Give it a try. See a demo fiddle here http://sqlfiddle.com/#!2/d918a/2
select t.id as tid,
t.name as tname,
case when ut.isdeleted = 0 then u.name else '' end as username
from team t
left join user_team ut
on t.name = ut.teamid
left join user u
on ut.userid = u.id;
Which will result in

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 ;)

chat application friend list

I have 3 MySQL tables namely chat_comments, chat_friends and user_details and I want to display a friend list.
My tables:
chat_comments(comment_id,comment,user_id,user_id2,date_added)
chat_friends(user_id,user_id2,approved)
user_details(user_id, mainimage_id, fullname)
To do this, I need a query that will return the needed fields (u.mainimage_id, u.fullname, b.comment, b.user_id) so I can loop through the list to display a table.
SQL so far (help from #Andriy M):
SELECT
cc.comment,
cc.date_added,
u.fullname,
u.mainimage_id
FROM
user_details u
LEFT JOIN
chat_comments cc
INNER JOIN (
SELECT
user_id,
MAX(comment_id) AS maxcomment
FROM chat_comments WHERE user_id=2020 OR user_id2=2020
GROUP BY user_id
) a ON a.user_id = cc.user_id
AND a.maxcomment = cc.comment_id
ON a.user_id = u.user_id
WHERE u.user_id IN (
SELECT user_id2
FROM chat_friends
WHERE user_id = 2020
AND approved = 1
)
The above query returns the last comment made by the logged-in user's friends in conversation not the last comment between the logged-in user and his/her friend regardless of who made it.
I would like it to return the last comment between the logged-in user and their friend individually regardless of who made it. In the chat_messages table, user_id is the sender and user_id2 is the receiver. Hope it makes sense?
Like #imm said in a comment, you need to use an outer join. In case of a left join, the user_details table should become the left side of the join, the right side being the result of your inner join of chat_comments with your a derived table. You'll also need to remove the user_id IN (…) condition from inside the a subselect and re-apply it to the user_details table. Here:
SELECT
cc.comment,
cc.date_added,
u.fullname,
u.mainimage_id
FROM
user_details u
LEFT JOIN
chat_comments cc
INNER JOIN (
SELECT
user_id,
MAX(comment_id) AS maxcomment
FROM chat_comments
GROUP BY user_id
) a ON a.user_id = cc.user_id
AND a.maxcomment = cc.comment_id
ON a.user_id = u.user_id
WHERE u.user_id IN (
SELECT user_id2
FROM chat_friends
WHERE user_id = 2020
AND approved = 1
)
;
Alternatively, you could use a right join. In this case you would just need to move the user_id IN (…) condition, similarly to the LEFT JOIN solution above, and replace the second INNER JOIN with RIGHT JOIN:
SELECT
cc.comment, cc.date_added, u.fullname, u.mainimage_id
FROM
(
SELECT user_id, MAX(comment_id) AS maxcomment
FROM chat_comments
GROUP BY user_id
) a
INNER JOIN
chat_comments cc ON
a.user_id = cc.user_id AND
a.maxcomment = cc.comment_id
RIGHT JOIN
user_details u ON
a.user_id = u.user_id
WHERE u.user_id IN (select user_id2 from chat_friends where user_id=2020 AND approved=1)