If you ended up here and you don't actually know what joins are yet,
then you should likely try the DBIx::Class::Manual::Intro instead.
Skip this part if you know what joins are..

But I'll explain anyway.
Assuming you have created your database in a more or less sensible way,
you will end up with several tables that contain related information.
For example,
you may have a table containing information about CDs,
containing the CD title and it's year of publication,
and another table containing all the Tracks for the CDs,
one track per row.

When you wish to extract information about a particular CD and all it's tracks,
You can either fetch the CD row,
then make another query to fetch the tracks,
or you can use a join.
Compare:

So, joins are a way of extending simple select statements to include fields from other, related, tables. There are various types of joins, depending on which combination of the data you wish to retrieve, see MySQL's doc on JOINs: http://dev.mysql.com/doc/refman/5.0/en/join.html.

In DBIx::Class each relationship between two tables needs to first be defined in the ResultSource for the table. If the relationship needs to be accessed in both directions (i.e. Fetch all tracks of a CD, and fetch the CD data for a Track), then it needs to be defined for both tables.

Once you have defined all your relationships, using them in actual joins is fairly simple. The type of relationship that you chose e.g. has_many, already indicates what sort of join will be performed. has_many produces a LEFT JOIN for example, which will fetch all the rows on the left side, whether there are matching rows on the right (table being joined to), or not. You can force other types of joins in your relationship, see the DBIx::Class::Relationship docs.

When performing either a search or a find operation, you can specify which relations to also refine your results based on, using the join attribute, like this:

The first argument to search is a hashref of the WHERE attributes, in this case a restriction on the Title column in the CD table, and a restriction on the name of the track in the Tracks table, but ONLY for tracks actually related to the chosen CD(s). The second argument is a hashref of attributes to the search, the results will be returned sorted by the id of the related tracks.

The special 'join' attribute specifies which relationships to include in the query. The distinction between relationships and tables is important here, only the relationship names are valid.

Another common use for joining to related tables, is to fetch the data from both tables in one query, preventing extra round-trips to the database. See the example above in "WHAT ARE JOINS".

Three techniques are described here. Of the three, only the prefetch technique will deal sanely with fetching related objects over a has_many relation. The others work fine for 1 to 1 type relationships.

In rare circumstances, you may also wish to fetch related data as incomplete objects. The usual reason to do is when the related table has a very large field you don't need for the current data output. This is better solved by storing that field in a separate table which you only join to when needed.

To fetch an incomplete related object, supply the dotted notation to the '+as' attribute:

However, this will produce broken objects. If the tracks id column is not fetched, the object will not be usable for any operation other than reading its data. Use the "Whole related objects" method as much as possible to avoid confusion in your code later.

Broken means: Update will not work. Fetching other related objects will not work. Deleting the object will not work.

For simplicity in the example above, the Artist was shown as a simple text field in the Tracks table, in reality, you'll want to have the artists in their own table as well, thus to fetch the complete set of data we'll need to join to the Artist table too.