MySQL exclude ids using joins - mysql

I have 2 tables:
uid uname
1 alex
2 anna
3 sergey
4 arnold
5 john
mid message uid
1 hello 3
2 DELETED 3
3 xcvcxv 4
4 bye 1
5 DELETED 2
6 4452 5
I would like to get all messages, but if message contains "DELETED", exclude this message' userID from all messages (after this message do not return messages from userID 3 and 2), using JOINs and without NOT IN.
Thanks for the help.

This should select all messages of users that don't have DELETED messages:
SELECT m.*
FROM message m
LEFT JOIN message m2
ON m2.uid = m.uid
AND m2.message = 'DELETED'
WHERE m2.mid IS NULL;

Related

How to check if two users have a common chat room?

Currently, I am trying to figure out how to find the common chat rooms between two users by checking their email addresses.
chat_rooms table:
id email chat_room_id
----------------------------------------------
1 johndoe#gmail.com 3
2 janedoe#gmail.com 3
3 test#gmail.com 42
4 check#gmail.com 64
5 janedoe#gmail.com 7
6 test#gmail.com 19
7 johndoe#gmail.com 6
How can I write a MySQL query that can return the common chat_room_id of johndoe#gmail.com and janedoe#gmail.com. Please advise.
You can do this with aggregation:
select chat_room_id
from mytable
where email in ('johndoe#gmail.com', 'janedoe#gmail.com')
group by chat_room_id
having count(*) = 2
This assumes that the same user cannot appear twice in the same room. If that's not the case, then you would just change the having clause to:
having count(distinct email) = 2
Or:
having min(email) <> max(email)

Group by 2 columns with 2 joins and return all rows with totals

I have 3 tables which I need to query where I need to group by 2 columns and also join the tables but still return all results.
Users
ID User_name Category Reason Change_date
1 John 1 2 2016-01-05
2 James 3 1 2015-10-02
3 Peter 1 4 2016-01-04
4 Tony 1 4 2016-01-15
5 Fred 1 4 2016-02-25
6 Rick 3 2 2016-04-19
7 Sonia 2 1 2016-10-14
8 Michelle 2 2 2015-11-09
9 Phillip 3 3 2016-03-01
10 Simon 3 3 2016-03-07
Category
ID Category_name
1 User
2 Super user
3 Admin
Reason
ID Reason_name
1 Promotion
2 Upgrade
3 Sponsor
4 Normal
I did some searching and found https://stackoverflow.com/a/28158276/1278201 and modified my query to try and use it:
SELECT category_name, reasons.reason_name, u1.id as user_id, user_name
from users as u1
JOIN (SELECT id from users where users.change_date BETWEEN '2016-01-01'
AND '2016-11-06' group by users.category, users.reason) AS u2
ON u1.id = u2.id
left join reason on u1.reason=category.id
left join category on u1.category=category.id
The results being returned are only using the group by - I should have 8 rows returned but I am only getting 5 which is one for each occurrence of each reason within each category.
My expected outcome is:
category_name reason_name user_id user_name
User Upgrade 1 John
"Upgrade" count 1
Normal 3 Peter
4 Tony
5 Fred
"Normal" count 3
"User" count 4
Super user Promotion 7 Sonia
"Promotion" count 1
"Super user" count 1
Admin Upgrade 6 Rick
"Upgrade" count 1
Sponsor 9 Phillip
10 Simon
"Sponsor" count 2
"Admin" count 3
How can I get all 8 rows returned as well as being able to get counts for each category_name and reason_name?
For what you are looking for in the expected output, this might be what you looking for:
SELECT
Category_name, reason_name, users.ID,User_name
FROM
Users
inner join Category on Category.ID=Users.Category
inner join Reason on Reason.ID=Users.Reason
where users.change_date BETWEEN '2016-01-01' AND '2016-11-06'
SQLFiddle
You shouldn't use GROUP BY in the subquery, because then it only returns one user ID from each group.
In fact, you don't need the subquery at all. You can just use a WHERE clause to select users that meet the change_date criteria.
SELECT category_name, reasons.reason_name, u1.id as user_id, user_name
from users as u1
left join reason on u1.reason=category.id
left join category on u1.category=category.id
where u1.change_date BETWEEN '2016-01-01' AND '2016-11-06'
To get subtotals of the groupings by category and reason, you can use GROUP BY and WITH ROLLUP.
SELECT category_name, reasons.reason_name, u1.id as user_id, user_name, COUNT(*) AS total
from users as u1
left join reason on u1.reason=category.id
left join category on u1.category=category.id
where u1.change_date BETWEEN '2016-01-01' AND '2016-11-06'
GROUP BY category_name, reason_name, user_id WITH ROLLUP
In the script that displays the results, the totals are in the rows where user_id is NULL. The category totals also have reason IS NULL. So you can display these rows appropriately in the script that displays the results. If you really need to do it all in MySQL, you can put the above query in a subquery, and the containing query can test for user_id IS NULL and reason_name IS NULL.

Select first row within same value of one column

I have these values in a table called message:
id message_id message
1 1 Hello sir
2 1 Hi dear.
3 2 Send by admin.
4 2 send by helper.
5 3 created by me.
6 3 Done by user.
What i wnat in result the table is below.
id message_id message
1 1 Hello sir
3 2 Send by admin.
5 3 created by me.
Any help please.
you can try as,all you need is just use a distinct clause which selects unique values.
SELECT DISTINCT * from meassage;
select M.id, M.message_id, M.message
from message M
WHERE M.ID = (SELECT MIN(M1.ID) FROM MESSAGE M1 WHERE M1.MESSAGE_ID = M.MESSAGE_ID) ;

SQL to get a particular thread based on two user

I recently build a thread based messaging system with the help from this post Thread Messaging
The 3 tables that involves are
member(member_id, member_userunique, and so on..)
thread_participant(thread_id, member_id)
message(message_id, message_subject, message_body, member_id, thread_id, and so on)
Within the participant table i have the following records
thread_id | member_id
1---------| 959
1---------| 1
1---------| 6
2---------| 959
2---------| 6
3---------| 959
3---------| 1
3---------| 6
And in the message table i have the following record (simplified version)
message_id | member_id | thread_id
1 ---------| 959 ------| 1
2 ---------| 959 ------| 2
3 ---------| 959 ------| 1
4 ---------| 959 ------| 1
5 ---------| 959 ------| 2
6 ---------| 959 ------| 3
7 ---------| 959 ------| 1
Hence we know that member id 959 and 1 are engage in 2 different threads, namely 3 (with message[s] id: 6) and 1 (with message[s] id: 1, 3 ,4 ,7).
However i am stuck with a particular query to get a particular thread based on two users.
So far this is the query that i have modified
SELECT m.message_id
FROM thread_participant AS participant
INNER JOIN message AS m ON participant.thread_id = m.thread_id
WHERE participant.member_id = 1 OR participant.member_id = 959
GROUP BY participant.thread_id
The query above is the short version of this query
SELECT message.message_id,
message.message_title, message.message_body,
message.message_sent_date,
user.member_userunique
FROM message AS message
INNER JOIN member AS user ON message.message_author = user.memberid
WHERE
(
message.message_id IN
(
SELECT m.message_id
FROM thread_participant AS participant INNER JOIN message AS m
ON participant.thread_id = m.thread_id
WHERE (participant.member_id IN (1,959))
GROUP BY participant.thread_id
)
)
AND message.message_title != 'UNDEFINED'
ORDER BY message.message_sent_date DESC
Note: The last query i am using the IN clause instead of the OR clause. There are more tables being used such as the Thread table which contains thread_id and creation_date.
Could anyone help me with this? Thx
Quick attempt (and not tested), but maybe using joins:-
SELECT a.message_id,
a.message_title, a.message_body,
a.message_sent_date,
z.member_userunique
FROM message a
INNER JOIN thread_participant b ON a.thread_id = b.thread_id AND b.member_id = 1
INNER JOIN thread_participant c ON a.thread_id = c.thread_id AND c.member_id = 959
INNER JOIN member z ON a.message_author = z.memberid
ORDER BY a.message_sent_date DESC
Select from the message table any message from a thread which has both specified members as a participant, joining back against the member table to get the details on the author of any message.

MySQL: Another max per group? Two tables

My database tracks sections users have completed:
Table 'users':
id user_id sections_id
//
4 46 1
5 46 2
6 46 4
7 46 5
//
Table 'sections':
id header_id name
1 1 1/3
2 1 2/3
3 1 3/3
4 2 1/3
5 2 2/3
6 2 3/3
The following query
SELECT a.sections_id
,b.header_id
FROM users a
JOIN sections b
ON a.sections_id = b.id
WHERE a.user_id = 46;
// a.user_id can be just user_id, but added for clarity
Gives me:
sections_id header_id
1 1
2 1
4 2
5 2
What I want is max section ID per header for a particular user, so that I know which section I need to serve the user:
sections_id header_id
2 1
5 2
I'm assuming this is a max per group problem, but I can't quite get my head around the solution. I could throw all the data into my PHP and parse out from there, but it seems I should be able to do it via the SQL. TIA!
This is a simple group by query:
SELECT s.header_id, max(u.sections_id)
FROM users u JOIN
sections s
ON u.sections_id = s.id
WHERE u.user_id = 46
group by s.header_id;
I also changed your aliases to be the initials of the table. This makes the query much easier to follow.
Edit: SQLFiddle Here: http://sqlfiddle.com/#!2/dbb5a/2
You could add a group by clause with a max() function
SELECT max(a.sections_id)
,b.header_id
FROM users a
JOIN sections b
ON a.sections_id = b.id
WHERE a.user_id = 46
GROUP BY header_id;