Restricting query results with fields on primary and joined entities
You can restrict the result set of a query
by applying predicates to both the primary and joined entities. You use
different techniques to add the predicates depending on whether you want
both (AND) or either (OR) to apply.
Using AND to combine predicates on primary and joined entities
If you need both predicates to apply to the result set, you can use a predicate method on the primary query and another predicate method on the secondary table.
For example, you want a query that returns all companies having a name that matches “Stewart Media” in the city of Chicago. The SQL statement for this query looks like:
SELECT * FROM pc_contact
JOIN pc_address
ON pc_address.ID = pc_contact.PrimaryAddressID
WHERE pc_contact.Subtype IN (1,8)
AND pc_contact.Name = 'Stewart Media'
AND pc_address.City = 'Chicago';
Using the query API, the primary entity type of your
query is Company, because
you want instances of that type in your result. You add the predicate
that specifies the restriction on the Name
property.
var queryCompany = Query.make(Company).compare(Company#Name, Equals, "Stewart Media")The Company entity does not have a
City property. That property
is on the Address entity.
You need to join the Address
entity to your query. You must capture the object reference that the
join method returns so
that you can specify predicates on values in Address.
var tableAddress = queryCompany.join(Company#PrimaryAddress)
tableAddress.compare(Address#City, Equals, "Chicago")
When you run the query, the result contains companies that have Chicago as the city on their primary addresses.
uses gw.api.database.Query
uses gw.api.database.Relop
// Start a new query with Company as the primary entity and restrict the result by company name.
var queryCompany = Query.make(Company).compare(Company#Name, Equals, "Stewart Media")
// Join Address as the dependent entity to the pimary entity Company.
var tableAddress = queryCompany.join(Company#PrimaryAddress)
// Add a predicate on the dependent entity.
tableAddress.compare(Address#City, Equals, "Chicago")
// Fetch the data with a for loop.
var result = queryCompany.select()
for (company in result) {
print (company + ", " + company.PrimaryAddress.City)
}
Running this code produces a list like the following one:
Stewart Media, Chicago
uses gw.api.database.Query
uses gw.api.database.Relop
// -- Query the Contact entity --
var queryContact = Query.make(Contact)
// -- Select only contacts that have a primary phone number that is a work phone
queryContact.compare(Contact#PrimaryPhone, Equals, typekey.PrimaryPhoneType.TC_WORK)
// -- Select only Contact instances that have a primary address in the city of Chicago --
queryContact.join(Contact#PrimaryAddress).compare(Address#City, Equals, "Chicago")uses gw.api.database.Query
uses gw.api.database.Relop
// -- Query the Contact entity --
var queryContact = Query.make(Contact)
// -- Add a predicate on the secondary entity
// -- Select only Contact instances that have a primary address in the city of Chicago --
var tableAddress = queryContact.join(Contact#PrimaryAddress)
tableAddress.compare(Address#City, Equals, "Chicago")
// -- Add a predicate on the primary entity
// -- Select only contacts that have a primary phone number that is a work phone
queryContact.compare(Contact#PrimaryPhone, Equals, typekey.PrimaryPhoneType.TC_WORK)Using OR to combine predicates on primary and joined entities
If you need either predicate to apply
to the result set, you use an or
method on the secondary table. To refer to a column on the secondary
table in the or block,
you can use a property reference. To refer to a column on the primary
table in the or block,
you must use a column reference. A property on the primary table is not
available in the context of the secondary table.
For example, you want a query that returns all companies either having a name that matches “Armstrong Cleaners” or in the city of Chicago. The SQL statement for this query looks like:
SELECT * FROM pc_contact
JOIN pc_address
ON pc_address.ID = pc_contact.PrimaryAddressID
WHERE pc_contact.Subtype IN (1,8)
AND (pc_contact.Name = 'Armstrong Cleaners'
OR pc_address.City = 'Chicago');
Using the query API, the primary entity type of your
query is Company, because
you want instances of that type in your result.
var queryCompany = Query.make(Company)The Company entity does not have a
City property. That property
is on the Address entity.
You need to join the Address
entity to your query. You must capture the object reference that the
join method returns so
that you can specify predicates on values in Address. You use an or block to add the predicate
that specifies the restriction on the Name
property in the Company
entity. You must use a column reference to access the Name column because that column
is not in the Address
entity.
var tableAddress = queryCompany.join(Company#PrimaryAddress)
tableAddress.compare(Address#City, Equals, "Chicago")
When you run the query, the result contains companies that have Chicago as the city on their primary addresses.
uses gw.api.database.Query
uses gw.api.database.Relop
// Start a new query with Company as the primary entity.
var queryCompany = Query.make(Company)
// Join Address as the dependent entity to the pimary entity Company.
var tableAddress = queryCompany.join(Company#PrimaryAddress)
// Add both predicates on the dependent entity.
tableAddress.or( \ or1 -> {
or1.compare(Address#City, Equals, "Chicago")
or1.compare(queryCompany.getColumnRef("Name"), Equals, "Armstrong Cleaners")
})
// Fetch the data with a for loop.
var result = queryCompany.select()
for (company in result) {
print (company + ", " + company.PrimaryAddress.City)
}
Running this code produces a list like the following one:
Armstrong Cleaners, San Ramon
Jones and West Insurance, Chicago
Shumway Contracting, Chicago
New Energy Corp., Chicago
...
Auto Claims of the West, Chicago
Auto Claims Defenders, Chicago
See also
