Understanding Query Results

Query results are returned as nested objects. The primary or “driving” object of the main SELECT statement in a SOQL query contains query results of subqueries.

For example, you can construct a query using either parent-to-child or child-to-parent syntax:

  • Child-to-parent:
    1SELECT Id, FirstName, LastName, AccountId, Account.Name
    2FROM Contact 
    3WHERE Account.Name LIKE 'Acme%'

    This query returns one query result (assuming there were not too many returned records), with a row for every contact that met the WHERE clause criteria.

    1
    2  "records": [
    3    {
    4      "attributes": {
    5        "type": "Contact",
    6        "url": "/services/data/v65.0/sobjects/Contact/003R000000A1BCDFXX"
    7      },
    8      "Id": "003R000000A1BCDFXX",
    9      "FirstName": "Jane",
    10      "LastName": "Doe",
    11      "AccountId": "001R000000Z1Y0xYAA",
    12      "Account": {
    13        "attributes": {
    14          "type": "Account",
    15          "url": "/services/data/v65.0/sobjects/Account/001R000000Z1Y0xYAA"
    16        },
    17        "Name": "Acme Corp (West)"
    18      }
    19    },
    20    {
    21      "attributes": {
    22        "type": "Contact",
    23        "url": "/services/data/v65.0/sobjects/Contact/003R000000A2CDEBZZ"
    24      },
    25      "Id": "003R000000A2CDEBZZ",
    26      "FirstName": "John",
    27      "LastName": "Smith",
    28      "AccountId": "001R000000Z1Y0zYBB",
    29      "Account": {
    30        "attributes": {
    31          "type": "Account",
    32          "url": "/services/data/v65.0/sobjects/Account/001R000000Z1Y0zYBB"
    33        },
    34        "Name": "Acme Global Solutions"
    35      }
    36    }
    37  ]
    38      
  • Parent-to-child:
    1SELECT Id, Name,
    2  (
    3    SELECT Id, FirstName, LastName
    4    FROM Contacts
    5  )
    6FROM Account
    7  WHERE Name like 'Acme%'

    This query returns a set of accounts, and within each account, a query result set of Contact fields containing the contact information from the subquery.

    1
    2         "records": [
    3    {
    4      "attributes": {
    5        "type": "Account",
    6        "url": "/services/data/v65.0/sobjects/Account/001R000000Z1Y0xYAA"
    7      },
    8      "Id": "001R000000Z1Y0xYAA",
    9      "Name": "Acme Corp (West)",
    10      "Contacts": {
    11        "totalSize": 2,
    12        "done": true,
    13        "records": [
    14          {
    15            "attributes": { "type": "Contact", "url": "/services/data/v65.0/sobjects/Contact/003R000000A1BCDFXX" },
    16            "Id": "003R000000A1BCDFXX",
    17            "FirstName": "Jane",
    18            "LastName": "Doe"
    19          },
    20          {
    21            "attributes": { "type": "Contact", "url": "/services/data/v65.0/sobjects/Contact/003R000000A3EFGHYY" },
    22            "Id": "003R000000A3EFGHYY",
    23            "FirstName": "David",
    24            "LastName": "Jones"
    25          }
    26        ]
    27      }
    28    },
    29    {
    30      "attributes": {
    31        "type": "Account",
    32        "url": "/services/data/v65.0/sobjects/Account/001R000000Z1Y0zYBB"
    33      },
    34      "Id": "001R000000Z1Y0zYBB",
    35      "Name": "Acme Global Solutions",
    36      "Contacts": {
    37        "totalSize": 1,
    38        "done": true,
    39        "records": [
    40          {
    41            "attributes": { "type": "Contact", "url": "/services/data/v65.0/sobjects/Contact/003R000000A2CDEBZZ" },
    42            "Id": "003R000000A2CDEBZZ",
    43            "FirstName": "John",
    44            "LastName": "Smith"
    45          }
    46        ]
    47      }
    48    }
    49  ]
    50      

The following sample illustrates how to process subquery results:

1private void querySample() {
2  QueryResult qr = null;
3  try {
4    qr = connection.query("SELECT a.Id, a.Name, " +
5      "(SELECT c.Id, c.FirstName, " +
6      "c.LastName FROM a.Contacts c) FROM Account a");
7    boolean done = false;
8    if (qr.getSize() > 0) {
9      while (!done) {
10        for (int i = 0; i < qr.getRecords().length; i++) {
11        Account acct = (Account) qr.getRecords()[i];
12        String name = acct.getName();
13        System.out.println("Account " + (i + 1) + ": " + name);
14        printContacts(acct.getContacts());
15        }
16        if (qr.isDone()) {
17          done = true;
18        } else {
19          qr = connection.queryMore(qr.getQueryLocator());
20        }
21      }
22    } else {
23      System.out.println("No records found.");
24    }
25    System.out.println("\nQuery succesfully executed.");
26  } catch (ConnectionException ce) {
27    System.out.println("\nFailed to execute query successfully, error message " +
28    "was: \n" + ce.getMessage());
29  }
30}
31
32private void printContacts(QueryResult qr) throws ConnectionException {
33  boolean done = false;
34  if (qr.getSize() > 0) {
35    while (!done) {
36    for (int i = 0; i < qr.getRecords().length; i++) {
37      Contact contact = (Contact) qr.getRecords()[i];
38      String fName = contact.getFirstName();
39      String lName = contact.getLastName();
40      System.out.println("Child contact " + (i + 1) + ": " + lName 
41      + ", " + fName);
42    }
43    if (qr.isDone()) {
44      done = true;
45    } else {
46      qr = connection.queryMore(qr.getQueryLocator());
47    }
48    }
49  } else {
50    System.out.println("No child contacts found.");
51  }
52}