I have 4 tables,
I'm trying to get all the chats that belong to the user with the id of 1, I can do that shown in the query below however I'm unsure of how efficient it is.
Secondly, I want to make this query a bit more complex by also getting all the other users which are in the chats along with the user that has the id of 1 however I'm unsure how to do this.
select * from chat_users left join chats on chat_users.chat_id = chats.id left join users on chat_users.user_id = users.id where user_id = 1
Users - id, username
Chats - id, chatname
chat_users id, user_id, chat_id
Posts - post, id, text
E.g.
If we imagine chats table as:
id : 1 | chatname : FirstChat
Chat_users as
id : 1 | user_id : 1 | chat_id : 1
id : 2 | user_id : 2 | chat_id : 1
Users as
id: 1 | username: firstUser
id: 2 | username: secondUser
I eventually want to end up with a query that returns all the chats that user1 is involved in along with the data for the other users in them chats however I'm not sure how I would do that?
Here is one way to phrase the query:
select c.*, u.*
from chat_users cu
inner join chats c on c.id = cu.chat_id
inner join users u on u.id = cu.user_id
where exists (
select 1 from chat_users cu1 where cu1.chat_id = cu.chat_id and cu1.user_id = 1
)
Perhaps you just want an aggregation:
select chat_id,
group_concat( case when cu.user_id <> 1 then user_id end) as other_users
from chat_users cu
group by chat_id
having sum( cu.user_id = 1 ) > 0;
This returns the chat id and the users -- which is what you are asking for. You can join in other information if you want.
Related
So i have 2 tables, users and messages
users table
uid, username
messages table
mid, senderid, receiverid, message, timestamp
The query i have at the moment is retrieving the uid, username and last timestamp of each chat conversation
SELECT DISTINCT
IF (messages.senderid = '5e9b95786a71f8.25790415', messages.receiverid, messages.senderid) as uid,
(SELECT username FROM users WHERE uid = IF (messages.senderid = '5e9b95786a71f8.25790415', messages.receiverid, messages.senderid)) as username,
MAX(messages.timestamp) as last_timestamp
FROM messages JOIN users ON users.uid = messages.senderid WHERE messages.senderid = '5e9b95786a71f8.25790415' OR messages.receiverid = '5e9b95786a71f8.25790415'
GROUP BY 1,2
which outputs below
uid | username | last_timestamp
1 | Developer | 1601826378
2 | BetaTester | 1601826301
What i need to add to this query is the message field which is based on the last_timestamp i have in the output.
How can the query be updated to include the extra message field?
Try this.
select A.uid, C.username, B.timestamp, B.message from (SELECT DISTINCT
IF (messages.senderid = '5e9b95786a71f8.25790415', messages.receiverid, messages.senderid) as uid,
MAX(messages.mid) as max_mid
FROM messages WHERE messages.senderid = '5e9b95786a71f8.25790415' OR messages.receiverid = '5e9b95786a71f8.25790415'
GROUP BY 1) A join messages B on A.max_mid = B.mid join users C on A.uid = C.uid
I'm a little confuse, since you already got last_timestamp why don't just left join message table again.
left JOIN messages m2 on last_timestamp = m2.timestamp and mid = m2.mid
and just select message column
select m2.message
I would like to write a query which retrieves name, id, and last modified date for each User. The below query gives the name, id, and last modified date from tables UserDetails1 and UserDetails2.
How could I modify this query to return a single date value, the max date for a given user_id in either of the details tables?
SELECT
id,
name,
MAX(userdetails1.date_modified),
MAX(userdetails2.date_modified)
FROM User user
INNER JOIN UserDetails1 userdetails1
ON userdetails1.user_id = user.id
INNER JOIN UserDetails2 userdetails2
ON userdetails2.user_id = user.id
User
id | name
---------
1 | name1
2 | name2
3 | name3
UserDetails1
user_id | date_modified
---------------------
1 | 2016-11-28 16:28:26
....
UserDetails2
user_id | date_modified
---------------------
1 | 2016-11-29 16:29:26
....
Try this, although I think there can be a more optimized way to write it.
SELECT
id,
name,
(CASE
WHEN MAX(userdetails1.date_modified) > MAX(userdetails2.date_modified)
THEN MAX(userdetails1.date_modified)
ELSE MAX(userdetails2.date_modified)
END)
FROM User user
INNER JOIN UserDetails1 userdetails1
ON userdetails1.user_id = user.id
INNER JOIN UserDetails2 userdetails2
ON userdetails2.user_id = user.id
GROUP BY id, name
One option is to UNION your two date tables together. This can be done before or after you JOIN. I personally would UNION before JOINING as it is simpler in my mind and to write.
Please excuse the SQL Server-esque syntax.
Before JOINing:
SELECT
u.id,
u.name,
MAX(d.date_modified) last_modified
FROM [User] u
INNER JOIN
(
SELECT user_id, date_modified
FROM UserDetails1
UNION ALL
SELECT user_id, date_modified
FROM UserDetails2
) d
ON u.id = d.user_id
GROUP BY u.id, u.name
After JOINing:
SELECT
id,
name,
max(date_modified) last_modified
FROM
(
SELECT
u.id, u.name, d.date_modified
FROM [User] u
INNER JOIN UserDetails1 d
ON d.user_id = user.id
UNION ALL
SELECT
u.id, u.name, d.date_modified
FROM [User] u
INNER JOIN UserDetails2 d
ON d.user_id = u.id
)
GROUP BY id, name
I have a blackout - I have the following table structure:
s_order:
userID | ....
s_user:
id | email | ...
I now loop through all my orders and can read the userID of the customer. I now want to check if there are other orders of this customer, not identified by his id but by his email address (because of migration, this can happen).
It can be, that in the s_user table I has the following data:
s_user:
id | email | ...
1 | hello#domain.com
2 | hello#domain.com
Can somebody help? Thanks!
Here is one method:
select u.*,
(case when exists (select 1
from s_order o2 join
s_user u2
on o2.user_id = u2.id
where u2.email = u.email and u2.id <> u.id
)
then 'Yes' else 'No'
end) as HasDuplicate
from s_user u;
However, it might be sufficient just to see if multiple users have the same email. If so, this is the easiest way:
select u.email, group_concat(u.id) as userid
from s_user u
group by u.email
having count(*) > 1;
You could limit this just to users with orders:
select u.email, group_concat(u.id) as userid
from s_user u
where u.id in (select o.user_id from s_order)
group by u.email
having count(*) > 1;
I would like to order the results by the count(*) of two related tables entries.
So I would like to get the top ordered user IDs that have more comments + posts interactions.
User Table:
ID Name ...
1 Jonh
2 Mark
3 King
4 Doe
Post Table:
ID USER_ID...
1 1
2 1
3 3
4 1
Comment Table:
ID USER_ID...
1 1
2 3
3 1
4 4
Ordered by POSTs count(*):
SELECT user.*, COUNT(post.user_id) AS count FROM user
LEFT JOIN post ON user.id = post.user_id
GROUP BY user.id
ORDER BY count DESC
Ordered by COMMENTs count(*)
SELECT user.*, COUNT(comment.user_id) AS count FROM user
LEFT JOIN comment ON user.id = comment.user_id
GROUP BY user.id
ORDER BY count DESC
Ordered by POSTs + COMMENTs count(*)
Expected Result:
user_id: 1 (four interactions), 3 (two interactions), 4 (one interaction)
SELECT u.*, COUNT(interact.user_id)
FROM user u
LEFT JOIN ( SELECT user_id FROM post
UNION ALL
SELECT user_id FROM comment
) interact
ON u.user_id = interact.user_id
GROUP BY u.user_id
If you want more detail can use conditional count
SELECT u.*,
COUNT(CASE WHEN source = 'p' then 1 END) as total_p,
COUNT(CASE WHEN source = 'c' then 1 END) as total_c,
COUNT(interact.user_id) as total_interact
FROM user u
LEFT JOIN ( SELECT user_id, 'p' as source FROM post
UNION ALL
SELECT user_id, 'c' as source FROM comment
) interact
ON u.user_id = interact.user_id
GROUP BY u.user_id
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