Content Types and the db tables they create
You can use views to create the queries for you so you can easily change your views in the back-office without the need of messing with custom code.
Or if you want to write the views yourself use the EntityFieldQuery class to create custom views without writing joins yourself because this is defenitivly not the way to do it.
You can load the full node object programmaticly by using node_load() and filter the fields you need. This loads the full node object so this can slow down the system when loading lots of nodes using node_load_multiple().
And finally if you think this isn't straightforward enough consider writing your own entity where you can add all fields inside your custom table(s) and get the entity data with simple queries. 
When using the views module you can add your entity to the views data by using hook_views_data. There is also the possibility of adding fields to your entity so this opens a lot of opportunities if really needed. It's a bit of extra work to install, especially the first time u use entities so you have to see if the budget allows room for testing and debugging. 
An introduction to entities