It is not clear what the question:
SELECT * FROM (
SELECT user_id, post_id, requested_on
FROM a
WHERE status != cancelled
UNION
SELECT user_id, post_id, time as requested_on
FROM b
WHERE type = ADD
) tbl1 GROUP BY user_id, post_id
means. Assume you have:
A, x, t1
A, x, t2
would you like the row with t1 or t2? If that does not matter lets apply an aggregate function such as MIN:
SELECT user_id, post_id, MIN(requested_on) FROM (
SELECT user_id, post_id, requested_on
FROM a
WHERE status <> cancelled
UNION
SELECT user_id, post_id, time as requested_on
FROM b
WHERE type = ADD
) tbl1
GROUP BY user_id, post_id
MySQL usually doesn't handle derived tables like this very well, is there any other predicate that you can apply to the parts in the union?