Hi, when using joins, you can always start with the most left source the way you would retrieve it normally. In this case your source is a custom table so you just query custom table items for that table.
var query =
Then you just extend this with the join using the Source method:
var query =
.Source(s => s
Left remains current, table is added as right, and if not fully qualified, column names for the ON condition are prefix with latest left and the new right tables. Optionally you can add condition to JOIN, or to the query itself.
If the left most table does not have native Kentico API, you can always use low-level DataQuery.
This really mostly is information from those two articles plus documentation for custom tables (https://docs.kentico.com/display/API9/Custom+table+data), you just sometimes need to decompose individual pieces of the information, and put some of them together the right way. I am sure you will learn this as you work more with it. In general it is a good practice to make an automated test, or some empty page, and just try various combinations and observe how they work together.
Hope this helped.