Making an inner join with the foreign key on the right

In SQL, an inner join is the default type of join. You make an inner join with the JOIN keyword. To be explicit about the type of join, use INNER JOIN. You specify the table that you need to join to the primary table of the query. You use the ON keyword to specify the columns that join the tables. By convention, you specify the join column on the primary table first. In the following SQL statement, the foreign key, UpdateUserID, is on the secondary table, pc_address. Because SQL considers the primary table to be on the left side, the foreign key is on the right side of the join. The query returns a result with all addresses and users who lasted updated them. The result contains all columns in the address and user tables.

SELECT * FROM pc_user
  INNER JOIN pc_address
    ON pc_user.ID = pc_address.UpdateUserID;

With the query builder APIs, you use the join method to specify an inner join. Use a property reference of the dependent entity and property name as a single parameter if the dependent entity has the foreign key. In these cases, the foreign key is on the right. The database must have a column that contains the foreign key. The data model definition of the column must specify foreignkey. You cannot use a column that is a onetoone or edgeForeignKey type because these types do not use a database column. To confirm that a foreign key uses a database field, in the Data Dictionary, check that the foreign key does not have “(virtual property)” text after its name.

Joining to a dependent entity with the foreign key on the right

In the following Gosu code, the dependent entity type, Address, has a foreign key, UpdateUser, which relates to the primary entity type, User.

var queryUser = Query.make(User) 
queryUser.join(Address#UpdateUser)

Similarly to SQL, you must specify the dependent entity to join, which in this case is Address. Unlike SQL, you do not specify the property on the primary entity, ID. The query builder APIs use metadata from the Data Dictionary to provide the missing information.

Applying predicates to the dependent entity

You seldom want to retrieve all instances of the primary type of a query. To select a subset, you often join a dependent entity and apply predicates to one or more of its properties. You apply these predicates for a secondary table with the foreign key on the right in the same way as for predicates where the foreign key is on the left.

For example, you want to select only users who have updated addresses in the city of Chicago. You must join the Address entity to your User query. Then, you can apply the predicate City = "Chicago" to Address, the dependent entity. The SQL for this query looks like the following lines.

SELECT DISTINCT pc_user.PublicID FROM pc_user
  INNER JOIN pc_address
    ON pc_user.ID = pc_address.UpdateUserID
    AND pc_address.City = 'Chicago';

The following Gosu code represents the same SQL query.

uses gw.api.database.Query
uses gw.api.database.Relop

// -- Query the User entity --
var queryUser = Query.make(User)

// -- Select only User instances who last updated addresses in the city of Chicago --
var tableAddress = queryUser.join(Address#UpdateUser)
tableAddress.compare(Address#City, Equals, "Chicago")

// -- Fetch the User instances with a for loop and print them --
var result = queryUser.select()

for (user in result) {
  print (user.DisplayName)
}

See also