MySQL group by with 2 columns when values are interchanged in columns

你离开我真会死。 提交于 2019-12-11 19:07:22

问题


See this table. It contains a chat log with incoming and outgoing messages

    id | to_number    | from_number  |message         | direction| type   |  generated_time
     1 | +15005550004 | +16232950692 |Hai             | OUTGOING |        | 2019-07-12 15:13:00
     2 | +16232950692 | +15005550004 |Hello           | INCOMING | REVIEW | 2019-07-13 18:13:00
     3 | +15005550004 | +16232950692 |How are you ?   | OUTGOING |        | 2019-07-13 21:15:00
     4 | +15005550001 | +16232950692 |Good morning    | OUTGOING |        | 2019-07-12 12:13:00
     5 | +16232950692 | +15005550001 |Have a nice day | INCOMING | REVIEW | 2019-07-12 12:17:00
     6 | +15005550007 | +16232950692 |Hey John        | OUTGOING |        | 2019-07-12 14:13:00

Now i want to get the last generated message in each threads in which we got an incoming message with type REVIEW. See the desired output

    to_number    | from_number  |message         | direction| type   | generated_time
    +15005550004 | +16232950692 |How are you ?   | OUTGOING |        | 2019-07-13 21:15:00
    +16232950692 | +15005550001 |Have a nice day | INCOMING | REVIEW | 2019-07-12 12:17:00

I tried a query

    select *
    from (select b.*
          from (select *
                from message m
                where m.id in (select min(msg.id)
                        from message msg
                        where msg.direction = 'INCOMING'
                        group by msg.from_number, msg.to_number)
                  and m.type = 'REVIEW') a
                 left join (select * from message m) b 
                  on ((a.from_number = b.to_number and a.to_number = b.from_number) or
                      (a.from_number = b.from_number and a.to_number = b.to_number))
          order by b.generated_time desc
    ) c group by from_number,to_number order by generated_time desc;

But it is not grouping the messages properly. Can anybody help me to find a solution for this ?


回答1:


One way to determine the "thread" for each row is CONCAT() the LEAST of the two numbers with the GREATEST of the same two numbers.

We can then GROUP BY on the "thread", to get the latest generated_time. In HAVING clause, we filter out only those "thread", which has atleast one 'INCOMING' message with 'REVIEW' type.

View on DB Fiddle

SELECT m1.*
FROM   message AS m1
       JOIN (SELECT Concat(Least(m.from_number, m.to_number), '|',
                                                      Greatest(m.from_number,
                                                      m.to_number))
                                              AS
                    thread,
                    Max(m.generated_time)
                                              AS max_generated_time
             FROM   message AS m
             GROUP  BY thread
             HAVING Sum(m.direction = 'INCOMING'
                        AND m.type = 'REVIEW')) AS dt
         ON dt.thread = Concat(Least(m1.from_number, m1.to_number), '|',
                                         Greatest(m1.from_number, m1.to_number))
            AND dt.max_generated_time = m1.generated_time;

Result

| id  | to_number    | from_number  | message         | direction | type   | generated_time      |
| --- | ------------ | ------------ | --------------- | --------- | ------ | ------------------- |
| 3   | +15005550004 | +16232950692 | How are you ?   | OUTGOING  |        | 2019-07-13 21:15:00 |
| 5   | +16232950692 | +15005550001 | Have a nice day | INCOMING  | REVIEW | 2019-07-12 12:17:00 |

Sidenote:

  1. Above approach (and your current schema design) is not able to use indexes, and hence it will not be performant.
  2. I would rather redesign the schema by creating two additional Master tables. One Master table would be storing the phone numbers: phone_id, and number
  3. Another Master table would be storing the "Thread", which will contain the phone_id values and thread_id. You can then use this thread_id in your message table, instead of storing the phone numbers.


来源:https://stackoverflow.com/questions/57033530/mysql-group-by-with-2-columns-when-values-are-interchanged-in-columns

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!