Add support for table aliases in joins

While being a convenience for long table tables, it also enables a table
to be joined with itself, which is often a useful operation.


Note: I also tried a version where you could specify the alias by passing an array as the first argument to the join function (for example .join(['accounts', 'a'])) but then I decided that the .joinAs(table, alias, ...) approach was more in line with the structure of your existing API. I'm happy to change it however you'd like.