Reputation: 867
I have a table called private_messages
with the following structure:
id message_from message_to
I am trying to determine the number of active chat rooms, but the table stores all messages sent and received, therefore there may be many rows where Alice
is in message_from
and in message_to
.
Assume my private_messages
table has 4 rows:
id message_from message_to
1 Alice conor
2 Alice conor
3 connor Alice
4 Anderson conor
The conversation between Alice and conor should be considered as 1
. Therefore when I echo, let's say $active_conversations
, the number 2
should be printed.
I am assuming this involved an array? i.e. $conversations = [];
. But I do not know or understand what to do beyond that.
Upvotes: 0
Views: 31
Reputation: 108450
One of the issues is that the tuples ('connor','Alice') and ('Alice','connor') in `private_messages` represent the same conversation/room whatever it is you are counting.
One approach would be get a total count of the distinct values, and divide by two, but that doesn't really seem like the right way to do it. (We can setup some edge cases where the result we get back isn't an integer, or is less than the actual number of active rooms.... e.g
id message_from message_to
-- ------------ ----------
1 Alice conor
2 Alice conor
3 conor Alice
4 Anderson conor
5 Cooper Alice
6 Dalton Allman
Another approach would be to reorder the values in the tuples (swapping message_from and message_to) on some rows that they match message_from and message_two on the other side of the conversation. For example, we could compare message_from and message_to, and swap them if message_to is "lower" than message_from.
As an illustration, using an expression to return values as displayed in the m_one and m_two columns.
id message_from message_to m_one t_two
-- ------------ ---------- ----- -----
1 Alice conor Alice conor
2 Alice conor Alice conor
3 conor Alice Alice conor
4 Anderson conor Anderson conor
5 Cooper Alice Alice Cooper
6 Allman Dalton Allman Dalton
And then we could count the distinct values of the (m_one,m_two) tuples.
A third approach would be to just discard any tuples where the message_from value is higher than the message_to, get rid of one side of the conversation/room. And then get a count of the distinct tuples that remain. But again, this would potentially exclude some conversations/rooms that had messages in only one direction.
id message_from message_to m_one t_two
-- ------------ ---------- ----- -----
1 Alice conor Alice conor
2 Alice conor Alice conor
3 conor Alice Alice conor
4 Anderson conor Anderson conor
5 Cooper Alice (NULL) (NULL)
6 Allman Dalton Allman Dalton
(We'll set aside a discussion of the the corner case of a conversation/room where message_from is equal to message_to.)
The SQL we write really depends on what algorithm we want to implement.
We could use a GROUP BY to collapse "matching" rows, and get a count. Or we could use a COUNT(DISTINCT foo)
to get a count of distinct values.
If we choose an algorithm that needs to "swap" values, we could use expressions that make use of the LEAST
and GREATEST
functions. Or MySQL IF() function, or CASE expressions.
If we want to exclude rows from being counted, we can include a predicate in the WHERE clause.
All of those are possible, and there are multiple ways to achieve the specified result.
Upvotes: 0
Reputation: 6202
If you just want to get a count of conversations, you can use something like this
SELECT COUNT(DISTINCT
CONCAT(
LEAST(message_from,message_to),
'->',
GREATEST(message_from,message_to)
)
) AS active_conversations
FROM private_messages;
output:
active_conversations
2
If you want to get details of the conversations you can use this
SELECT DISTINCT
LEAST(message_from,message_to) as FirstPerson,
GREATEST(message_from,message_to) as SecondPerson
FROM private_messages;
output:
FirstPerson SecondPerson
Alice conor
Anderson conor
Upvotes: 0
Reputation: 2202
select count(id) from private_messages group by message_from,message_to
then you get appropriate result
Upvotes: 0