User-tracking history query I have a query consisting of UNIONs.

 SELECT CONCAT("You sent track request to ",u.username) AS ACTION, h.`dateTime`  FROM login_user u
LEFT JOIN
history h ON u.id = h.`toUserId` WHERE h.`fromUserId`=28 AND h.`Action`="Request"
UNION
SELECT CONCAT("You Accepted track request from ",u.username) AS ACTION, h.`dateTime`  FROM login_user u
LEFT JOIN
history h ON u.id = h.`toUserId` WHERE h.`fromUserId`=28 AND h.`Action`="Accept"
UNION
SELECT CONCAT("You Denied track request from ",u.username) AS ACTION, h.`dateTime`  FROM login_user u
LEFT JOIN
history h ON u.id = h.`toUserId` WHERE h.`fromUserId`=28 AND h.`Action`="Deny"
UNION
SELECT CONCAT(u.username, " sent you Track Request") AS ACTION, h.`dateTime`  FROM login_user u
LEFT JOIN
 history h ON u.id = h.FromUserId WHERE h.`toUserId`=28 AND h.`Action`="Request"
  UNION
 SELECT CONCAT(u.username, " accepted your track request") AS ACTION, h.`dateTime`  FROM login_user u
 LEFT JOIN
 history h ON u.id = h.`fromUserId` WHERE h.`toUserId`=28 AND h.`Action`="Accept"
 UNION
 SELECT CONCAT(u.username, " Denied your track request") AS ACTION, h.`dateTime`  FROM login_user u
 LEFT JOIN
 history h ON u.id = h.`fromUserId` WHERE h.`toUserId`=28 AND h.`Action`="Deny"


Since all the constituent queries are almost same, I was wondering if I can use CASE or something to shorten and optimize the query?
These constituent queries will never generate overlapping results, since their ACTION columns are all distinct.  Therefore, you should be using UNION ALL instead of UNION to avoid the deduplication effort.

Also, I suspect you should be using INNER JOIN instead of LEFT JOIN because I doubt that you are interested in historical events that didn't occur.

For portability, string literals should be written using single quotes, like 'Request', rather than "Request".  Allowing double quotes for string literals is a MySQLism — standard SQL uses double quotes for identifiers, the way MySQL uses backticks.

Take care to be consistent in your indentation and capitalization.  You wrote h.FromUserId instead of h.`fromUserId` in one case.  You also call the result column ACTION, which is capitalized differently from history.Action.  The result also had "Accepted", "Denied", and "Track Request" oddly capitalized in various places.

Anyway, to address your specific concern, I think that this formulation using CASE could work for you.

SELECT Action, dateTime
    FROM (
        SELECT CASE
               WHEN h.Action = 'Request' THEN CONCAT('You sent track request to ', u.username)
               WHEN h.Action = 'Accept'  THEN CONCAT('You accepted track request from ', u.username)
               WHEN h.Action = 'Deny'    THEN CONCAT('You denied track request  from ', u.username)
               END CASE AS Action
             , h.dateTime
             , h.fromUserId AS self
            FROM history h
                INNER JOIN login_user u
                    ON h.toUserId = u.id
            WHERE h.Action IN ('Request', 'Accept', 'Deny')    -- possibly superfluous
        UNION ALL
        SELECT CASE
               WHEN h.Action = 'Request' THEN CONCAT(u.username, ' sent you track request')
               WHEN h.Action = 'Accept'  THEN CONCAT(u.username, ' accepted your track request')
               WHEN h.Action = 'Deny'    THEN CONCAT(u.username, ' denied your track request')
               END CASE AS Action
             , h.dateTime
             , h.toUserId AS self
            FROM history h
                INNER JOIN login_user u
                    ON h.fromUserId = u.id
            WHERE h.Action IN ('Request', 'Accept', 'Deny')    -- possibly superfluous
    ) AS msg
    WHERE self = 28
    ORDER BY dateTime;