Standard database tables can be used instead of using a datastore if you like.
There are some examples of this in the code. One example from the jrChainedSelect module:
$tbl = jrCore_db_table_name('jrChainedSelect', 'sets');
$req = "SELECT * FROM {$tbl} WHERE set_id = {$sid} LIMIT 1";
$_rt = jrCore_db_query($req, 'SINGLE');
so you can build tables and join them however you like.
The concept of the datastore is that you dont need to define database structure. And that any other modules can add to your modules data if they need to.
So there really shouldn't bee a need for a union or a join, the data should just be there in the datastore.
One example of this is the jrTags module that allows users to tag items like an audio item.
As well as storing the tags in its own datastore for look up, it also writes the tag directly to the datastore of the jrAudio module.
So when someone gets a list of audio items, the tags just come back as part of the item.
------
If your wanting to add your (something) into the results for an item list lookup, you can use the 'events' and 'listeners' system to listen for when that/those item(s) are requested and inject whatever you want to add in when the results are returned.