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

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}