Your understanding is mostly correct about them, though to add more.
- Joins enable to reporting on data from more than multiple classes or tables. Like SQL join, we have to define the logical condition for the match or join corresponding to instances of the classes or tables. It too has the similar concept of "Left Outer Join/Right Outer Join" or "Inner Join".
A sub-report is a report definition that provides some or all of its results to another report definition that invokes it. Using a report definition as a sub-report does not change it in any way, and the original report can still be accessed directly in its own right.
Users can designate sub-reports within report definitions to simplify assembling data from several classes, or to satisfy complex conditions.
For example, the requirements for a report might state: "For each operator, show information (ID, label, status, last update) for the last work item they updated within a given work type." A way to accomplish this would be:
Build a sub-report that retrieves the most recent (MAX) update date by update operator within the work type.
Build the main report to select the task information for all work items.
Within the main report reference the sub-report, matching the update operator and the update date columns in the two reports.
Display data about those work items that satisfy the criteria for both reports.