I'm trying to figure out how I can query my table to see if a group of user_id's match a conversation_id.
Query 1 should return result for:
user_id 1 is looking to see if there are any conversation_id's with just user_id = 2 and user_id = 1 in it. (Should return a row for each conversation_id = 1, 2, 4, 5 based on SQL Fiddle example)
conversation_id
1
2
4
5
Query 2 should return result for:
user_id 1 is looking to see if there are any conversation_id's with user_id = 2, user_id = 1, and user_id = 4 in it. (Should return 0 rows as it doesn't exist in the SQL Fiddle example)
The table setup is located at
SQL Fiddle
You can use a combination of group by ... having and a correlated exists subquery to achieve the result you want:
-- Query 1:
SELECT
conversation_id
FROM
users_conversations uc
where not exists (
select 1 from users_conversations
where conversation_id = uc.conversation_id
and user_id not in (1,2)
)
group by conversation_id
having count(distinct user_id) = 2;
-- Query 2: same query, only different numbers.
SELECT
conversation_id
FROM
users_conversations uc
where not exists (
select 1 from users_conversations
where conversation_id = uc.conversation_id
and user_id not in (1,2,4))
group by conversation_id
having count(distinct user_id) = 3;
Sample SQL Fiddle
Note that the first query will not return 1,2,4,5 but rather 2,5 but in your sample data neither 1 or 4 has only user_id 1 and 2 as participants (conversation 1 has 1,2,3,4, and conversation 4 has 1,2,5).
If i understand it right it should be something like his.
Q1:
SELECT
CASE
WHEN
count(distinct CASE WHEN user_id in ('1','2') THEN user_id END)>='2'
THEN `conversation_id`
END 'test'
FROM
users_conversations
where 1
group by `conversation_id`
Q2:
SELECT
CASE
WHEN
count(distinct CASE WHEN user_id in ('1','2','4') THEN user_id END)>='3'
THEN `conversation_id`
END 'test'
FROM
users_conversations
where 1
group by `conversation_id`
http://sqlfiddle.com/#!9/fb29d/9
Related
I'm have a table with following structure and data. I would like to get the conversation_id of a row that having given user_id(s).
For example. I would like to get the conversation_id between user_id 1 and user 2, so the result should be 1. If I would like to get the conversation_id of user_id 1 to 4, the result should be 4.
How could I write in sql query?
You can GROUP BY conversation_id and set the condition in the HAVING clause:
SELECT conversation_id
FROM tablename
WHERE user_id IN (1, 2) -- the ids of the users
GROUP BY conversation_id
HAVING COUNT(DISTINCT user_id) = 2 -- the number of the users
I am doing a selection using GROUP BY, so I get a lot of different rows. What I need is to UPDATE the status field of each row affected by the SELECT query, but it is grouped... so I don't know all the ids, just the MAX(id).
This is the select query:
SELECT d.*, n.* FROM
(SELECT MAX(id) as id, MAX(datetime) as datetime, COUNT(DISTINCT content) as total FROM user_notifications
WHERE id_user
GROUP BY id_ref, type
ORDER BY datetime DESC) d
JOIN user_notifications n USING (id)
Edit:
Simple example, this is the table
id user content status
1 1 aaa 0
2 1 aaa 0
3 1 bbb 0
4 2 aaa 0
5 3 bbb 0
this is the query
select max(id), user, content from table where user=1 group by content
this is the result
id user content
2 1 aaa
3 1 bbb
in this query in fact sql internally select all user=1 (id= 1, 2, 3) and then the query is grouped, showing just two rows.
So, I want to update all ids involved in the query (id= 1 , 2 and 3)
Based on your example, you need the result exact to this query:
select id from `table` where user = 1;
But by using the query you provided which groups record by content
select max(id), user, content from `table` where user = 1 group by content
So, in such case you can join same table with derived table:
select id from `table` as t
join (select max(id), user, content from `table` where user = 1 group by content) as dt
on dt.content = t.content and dt.user = t.user;
This query is now equivalent to first straight forward query.
Have a table for chat where I collect user_from, user_to and other non important stuffs for the example.
Want to get user_id's for all the users related in conversation (with where clause for current user_id).
In the example below I'm trying to search all the users where user_id=1 exist, but I know that doesn't work and don't know how to make it works.
SELECT *
FROM messages M
WHERE M.user_from="1" OR M.user_to="1"
GROUP by m.user_from, m.user_to
If in table are rows (below). Actually I want to receive finally array([0]=>2, [1]=>4), because user_id=1 have conversation only with user_id=2 and user_id=4
user_from | user_to
1 2
1 2
2 1
1 4
3 2
Probably I have to use Select in the Select or use anykind of Case When Then, but have no idea how to loop it correctly
RESOLVED WITH ORDERING BY LAST MSG_ID!!!
SELECT (IF( user_from = 1, user_to, user_from )) as user_id
FROM messages
WHERE `user_from` = 1 OR `user_to` = 1
GROUP BY user_id
ORDER BY MAX(msg_id) DESC
select user_to as user_id
from messages
where user_from = 1
union
(select user_from as user_id
from messages
where user_to = 1)
edited on suggestion from #Анжел Миленов - (I do not personally know why the brackets make a difference in mySql)
this is my conversation table:
conversationID || userID
1 || 1
1 || 2
2 || 1
2 || 2
2 || 3
as you can see each conversation can contain 2 users or more.
I am trying to get the id of the conversation that only 2 users are there.
ie conversation that contains only users 1 & 2, the answer is conversation 1.
but how do I get it?
This will select all conversations that have users 1 or user 2, or both, but no one else:
select conversationID
from conversations
group by conversationID
having count(*) = count(case when userID in (1,2) then 1 end)
If you also want all conversations that have exactly user 1 and 2, and no one else, you also have to add an and condition:
select conversationID
from conversations
group by conversationID
having count(*) = count(case when userID in (1,2) then 1 end)
and count(*) = 2 -- number of elements in set
If userID can be duplicated, it's also better to use distinct:
select conversationID
from conversations
group by conversationID
having
count(distinct userID) = count(distinct case when userID in (1,2) then userID end)
and count(distinct userID) = 2 -- number of elements in set
You should use having clause. Assuming that ( conversationID, userID ) is PK or AK, your query is:
select conversationID
from your_Table
group by conversationID
having count( * ) = 2
Edited Joined with 1,2 user conversations, this is the index friendly approach with out correlate subquery and without function by row.
select t1 conversationID
from your_Table t1
inner join
( select distinct conversationID
from your_Table
where userId in (1, 2)
) t2
on t1.conversationID = t2.conversationID
group by t1.conversationID
having count( distinct t1.userId ) = 2
Hope this helps you,
select conversationID from conversation
group by ConversationID having count(distinct UserID)=2;
sqlfiddle demo
I have table with, folowing structure.
tbl
id name
1 AAA
2 BBB
3 BBB
4 BBB
5 AAA
6 CCC
select count(name) c from tbl
group by name having c >1
The query returning this result:
AAA(2) duplicate
BBB(3) duplicate
CCC(1) not duplicate
The names who are duplicates as AAA and BBB. The final result, who I want is count of this duplicate records.
Result should be like this:
Total duplicate products (2)
The approach is to have a nested query that has one line per duplicate, and an outer query returning just the count of the results of the inner query.
SELECT count(*) AS duplicate_count
FROM (
SELECT name FROM tbl
GROUP BY name HAVING COUNT(name) > 1
) AS t
Use IF statement to get your desired output:
SELECT name, COUNT(*) AS times, IF (COUNT(*)>1,"duplicated", "not duplicated") AS duplicated FROM <MY_TABLE> GROUP BY name
Output:
AAA 2 duplicated
BBB 3 duplicated
CCC 1 not duplicated
For List:
SELECT COUNT(`name`) AS adet, name
FROM `tbl` WHERE `status`=1 GROUP BY `name`
ORDER BY `adet` DESC
For Total Count:
SELECT COUNT(*) AS Total
FROM (SELECT COUNT(name) AS cou FROM tbl GROUP BY name HAVING cou>1 ) AS virtual_tbl
// Total: 5
why not just wrap this in a sub-query:
SELECT Count(*) TotalDups
FROM
(
select Name, Count(*)
from yourTable
group by name
having Count(*) > 1
) x
See SQL Fiddle with Demo
The accepted answer counts the number of rows that have duplicates, not the amount of duplicates. If you want to count the actual number of duplicates, use this:
SELECT COALESCE(SUM(rows) - count(1), 0) as dupes FROM(
SELECT COUNT(1) as rows
FROM `yourtable`
GROUP BY `name`
HAVING rows > 1
) x
What this does is total the duplicates in the group by, but then subtracts the amount of records that have duplicates. The reason is the group by total is not all duplicates, one record of each of those groupings is the unique row.
Fiddle: http://sqlfiddle.com/#!2/29639a/3
SQL code is:
SELECT VERSION_ID, PROJECT_ID, VERSION_NO, COUNT(VERSION_NO) AS dup_cnt
FROM MOVEMENTS
GROUP BY VERSION_NO
HAVING (dup_cnt > 1 && PROJECT_ID = 11660)
I'm using this query for my own table in PHP, but it only gives me one result whereas I'd like to the amount of duplicate per username, is that possible?
SELECT count(*) AS duplicate_count
FROM (
SELECT username FROM login_history
GROUP BY username HAVING COUNT(time) > 1
) AS t;