views:

99

answers:

0

I'm working on a messaging application and am trying to find the number of new messages and the date of the most recent messages for all users with whom the current user has active conversations.

The following query works, but expanding on it would mean I'd have to run the aggregate subquery twice to get both the count and last sent time values:

SELECT u.uid, u.name, 
  (
    SELECT count(s.mid)
    FROM im_msg s 
    WHERE s.ruid=1 
    AND s.suid = m.their_uid 
    AND s.received_time = '0000-00-00 00:00:00'
  ) AS new_msgs,
  (
    SELECT max(s.sent_time)
    FROM im_msg s 
    WHERE s.ruid=1 
    AND s.suid = m.their_uid 
    AND s.received_time = '0000-00-00 00:00:00'
  ) AS last_msg_time
FROM (
        (
          SELECT received_time, m1.ruid as ruid, m1.suid AS my_uid, m1.ruid AS their_uid, m1.sent_time 
          FROM im_msg m1
          WHERE m1.suid=1
          AND m1.sender_deleted=0
        )
      UNION
        (
          SELECT received_time, m2.ruid as ruid, m2.ruid AS my_uid, m2.suid AS their_uid, m2.sent_time 
          FROM im_msg m2
          WHERE m2.ruid=1
          AND m2.receiver_deleted=0
        )
    ) AS m, 
    users u
WHERE u.uid = m.their_uid
AND m.my_uid = 1 
AND (
  (m.ruid=1 AND m.received_time = '0000-00-00 00:00:00')
  OR m.sent_time > DATE_SUB(NOW(), INTERVAL 1 HOUR)
)
GROUP BY m.their_uid
ORDER BY last_msg_time DESC

The following query does not work -- apparently MySQL doesn't like my using a value from one subquery in the WHERE clause of another. This throws an error "Unknown column 'm.their_uid' in 'where clause'".

SELECT u.uid, u.name, 
  all_new.num_new AS new_msgs, 
  all_new.newest_time AS last_msg_time
FROM (
        (
          SELECT received_time, m1.ruid as ruid, m1.suid AS my_uid, m1.ruid AS their_uid, m1.sent_time 
          FROM im_msg m1
          WHERE m1.suid=1
          AND m1.sender_deleted=0
        )
      UNION
        (
          SELECT received_time, m2.ruid as ruid, m2.ruid AS my_uid, m2.suid AS their_uid, m2.sent_time 
          FROM im_msg m2
          WHERE m2.ruid=1
          AND m2.receiver_deleted=0
        )
    ) AS m, 
    users u,
    (
      SELECT count(mid) AS num_new, MAX(s.sent_time) AS newest_time
      FROM im_msg s 
      WHERE s.ruid=1 
      AND s.suid = m.their_uid 
      AND s.received_time = '0000-00-00 00:00:00'
    ) AS all_new
WHERE u.uid = m.their_uid
AND m.my_uid = 1 
AND (
  (m.ruid=1 AND m.received_time = '0000-00-00 00:00:00')
  OR m.sent_time > DATE_SUB(NOW(), INTERVAL 1 HOUR)
)
GROUP BY m.their_uid
ORDER BY last_msg_time DESC

Is there a way to do this with just the one subquery, or do I have to run the subquery twice?