简体   繁体   中英

MySql Query with UNION and SORT

Actually i am trying to create a conversation interface like FB(Messages) and for that a sql query is used to fetch all the persons whom with user is talked already. I need the id of the user from whom he had talked in descending order, Like if A has chatted with B and C. Then B AND C will be result of that query and B will come first because A chatted with B recently.

My 'messages' table structure is : http://www.softnuke.com/me/files/DB.png

This is the FB example: http://www.softnuke.com/me/files/msg.png

This is my incorrect query which needs to be fixed:

SELECT DISTINCT(`mates`)FROM(
    SELECT `time` AS `time`,`from_id` AS `mates` 
     FROM `messages` AS T WHERE (`from_id`=$uid OR `to_id`=$uid) 

    UNION

    SELECT `time` AS `time`,`to_id` AS `mates`
    FROM `messages` AS T WHERE (`from_id`=$uid OR `to_id`=$uid) 

    ) AS T 
    WHERE `mates`!='$uid'
    ORDER BY `time`

$uid will give me the variable of the user I want to fetch List(Here its A).

You seem to be getting the main person and the person they were talking to, irrespective of which one is the main person. Also not quite sure how MySQL will work out the time to order things by when you are using DISTINCT which will remove some of the records with their times.

You could get the max time and order by that:-

SELECT `mates`, MAX(`time`) AS LatestConv
FROM(
    SELECT `time` AS `time`,`from_id` AS `mates` 
     FROM `messages` AS T WHERE `to_id`=$uid

    UNION

    SELECT `time` AS `time`,`to_id` AS `mates`
    FROM `messages` AS T WHERE `from_id`=$uid 

    ) AS T 
GROUP BY `mates`
ORDER BY LatestConv

To get the status of that latest message:-

SELECT a.mates, a.LatestConv, IFNULL(b.Status, c.Status)
FROM
(
    SELECT mates, MAX(`time`) AS LatestConv
    FROM(
        SELECT `time` AS `time`, from_id AS mates 
        FROM messages AS T 
        WHERE to_id = $uid
        UNION
        SELECT `time` AS `time`, to_id AS mates
        FROM messages AS T 
        WHERE from_id = $uid 
        ) AS T 
    GROUP BY `mates`
) a
LEFT OUTER JOIN messages b
ON a.mates = b.from_id AND a.LatestConv = b.`time` AND b.to_id = $uid
LEFT OUTER JOIN messages c
ON a.mates = c.to_id AND a.LatestConv = c.`time` AND c.from_id = $uid
ORDER BY LatestConv

Note that this might get a touch confused if there are multiple messages to the same person which all share the same latest time. If this is likely it could be coped with as follows:-

SELECT a.mates, a.LatestConv, MAX(IFNULL(b.Status, c.Status))
FROM
(
    SELECT mates, MAX(`time`) AS LatestConv
    FROM(
        SELECT `time` AS `time`, from_id AS mates 
        FROM messages AS T 
        WHERE to_id = $uid
        UNION
        SELECT `time` AS `time`, to_id AS mates
        FROM messages AS T 
        WHERE from_id = $uid 
        ) AS T 
    GROUP BY `mates`
) a
LEFT OUTER JOIN messages b
ON a.mates = b.from_id AND a.LatestConv = b.`time` AND b.to_id = $uid
LEFT OUTER JOIN messages c
ON a.mates = c.to_id AND a.LatestConv = c.`time` AND c.from_id = $uid
GROUP BY a.mates, a.LatestConv
ORDER BY LatestConv

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM