What I understand from your question, you seem to need a correlated query that looks like this:
(SELECT firstName, lastName, user.userName, modifiedTimestamp FROM user, userInfo ui1 WHERE user.userName=userInfo.userName AND modifiedtimestamp=(select max(modifiedtimestamp) from userInfo ui2 where ui1.userName=ui2.userName)) UNION (SELECT firstName, lastName, user.userName, modifiedTimestamp FROM user, userProgram up1 WHERE user.userName=userProgram.userName AND modifiedtimestamp=(select max(modifiedtimestamp) from userProgram up2 where up1.userName=up2.userName)) ORDER BY modifiedTimestamp DESC;
So, am I continuing to move on to this result? Key: To clearly express the information you want to receive, without accepting mental abbreviations.
Step 1. Select the fields that I need in the different tables of my database. This is what is between SELECT and FROM. It seems obvious, but it becomes less obvious when it comes to aggregation functions, such as amounts or bills. In this case, you should say, for example: "I need to count the lines in userInfo for each firstName." See below under GROUP BY.
Step 2: Knowing the desired field, write the connections between the various corresponding tables. It is easy ...
Step 3: Express your terms. It can be easy, for example, if you need user data for userName = "RZEZDFGBH" or more complex, as in your case: a way to formulate it so that you can do it if you want only the most recently changed label, "so that the changed label was equal to the most recently changed label "(which is where you can easily take the mental label and skip the point)
Step 4: If you have aggregates, it's time to install the GROUP BY statement. For example, if you count the entire line in userInfo for each firstName, you should write "GROUP BY firstName":
SELECT firstName,count(*) FROM userInfo GROUP BY firstName
This gives you the number of entries in the table for each other firstName.
Step 5: Terms. These are the conditions for the units. In the previous example, if you only need data for firstName having more than 5 rows in the table, you can write SELECT firstName,count(*) FROM userInfo GROUP BY firstName HAVING count(*)>5
Step 6: Sort with ORDER BY. Pretty easy ...
This is just a brief summary. There is much, much more to discover, but it would be too long to write an entire SQL course here ... Hope this helps, though!