What It Does
The addJoinQuery() method creates an INNER JOIN between your current GlideRecord table and another table in the database. ServiceNow translates this into a SQL JOIN clause that executes as a single database query rather than multiple separate queries. The method returns a GlideQueryCondition object that represents the joined table, allowing you to add WHERE conditions against fields in that joined table.
Internally, ServiceNow builds a composite query that includes both your original table and the joined table. When you call query() on the GlideRecord, the platform generates SQL similar to SELECT main.* FROM main_table main INNER JOIN join_table jt ON main.primary_field = jt.join_field WHERE [your conditions]. The actual records you iterate through are still from your original table, but the JOIN ensures only records that have matching related records are returned.
The method always returns a GlideQueryCondition object, never null or undefined. Even if the table names or field names are invalid, the method succeeds and returns a condition object. The error only surfaces when you execute the query with query(), at which point ServiceNow will log a database error and return no results rather than throwing an exception.
One critical edge case involves reference fields with nil values. If your primaryField contains empty reference values, those records will be excluded from your results because INNER JOINs only return rows where both sides of the join have matching values. Records with null reference fields simply disappear from your result set, which can be surprising if you expected to see all records from the main table.
The addJoinQuery() method works alongside addQuery() and other query methods. You can call multiple addJoinQuery() methods on the same GlideRecord to join multiple tables, creating increasingly complex queries. Each call returns its own GlideQueryCondition that operates independently on its respective joined table.
When to Use This
Use addJoinQuery() when you need to filter your main table based on conditions in a related table, especially when the relationship involves reference fields. This is perfect for scenarios like finding all incidents assigned to users in a specific department, or all catalog requests where the requested item is from a particular category. The method shines when you want to avoid the performance penalty of nested queries or multiple database round trips.
Avoid addJoinQuery() when you simply need to access reference field values from related records. Use dot-walking with gr.assigned_to.department instead. Also avoid it when you need records from the main table even if the related table has no matching records—in those cases, you'll need to use separate queries or check for null reference values explicitly. Don't use addJoinQuery() for simple reference field existence checks where addQuery('reference_field', '!=', '') would be more straightforward.
A common misuse pattern involves trying to access fields from the joined table directly on the main GlideRecord after the query executes. The JOIN affects which records are returned, but it doesn't merge the tables—you still need to use dot-walking or separate queries to access the joined table's field values. Another mistake is assuming addJoinQuery() performs a LEFT JOIN—it's always an INNER JOIN, so records without matching related records will be filtered out.
Return Value
Returns a GlideQueryCondition object that represents the joined table in the query context. This condition object supports the same methods as any other query condition: addCondition(), addOrCondition(), and operators like addCondition('field', 'CONTAINS', 'value'). The object is never null and remains valid until you execute the query or create a new GlideRecord instance.
The condition object doesn't validate field names or table references until query execution. You can chain method calls on invalid conditions, but the query will fail silently when executed, returning zero results rather than throwing an exception. Always test your join queries with known data to verify the table and field references are correct before deploying to production.
Enjoying this? Get one deep-dive per week.
Join 1,000+ ServiceNow pros — scripts, GlideRecord patterns, Flow Designer techniques, and career moves. Free.
Platform Behavior & Side Effects
- Business Rules, ACLs, and security restrictions apply only to the main table—the joined table's security is not automatically enforced during the query
- No data is written to the database—this is purely a query construction method that affects only the SELECT statement
- Query performance is generally faster than separate queries but slower than simple single-table queries—database indexes on join fields are critical
- The method works identically in Business Rules, Script Includes, and Scheduled Jobs—no behavioral differences based on execution context
- Query results are not cached by default—each execution hits the database unless you're within a cached GlideRecord scope
- Multiple join queries on the same GlideRecord create multiple INNER JOINs in the final SQL, potentially causing exponential result filtering
- Domain separation applies to both tables in the join—records will be filtered based on the user's domain access to both the main and joined tables