SOQL, short for Salesforce Object Query Language, is the language you use to read records out of your org. A query names the fields you want, the object they live on and the conditions a record has to meet, in the same SELECT, FROM and WHERE pattern that SQL uses. SOQL for admins comes down to a short list of clauses and a few habits, and once you have them you can answer questions that reports cannot. A SOQL statement retrieves data. Changing records takes a different tool, such as a flow, Data Loader or Apex.
A report is built on a report type, and the report type decides which objects and relationships you can reach. A query goes straight to the object, follows relationships in both directions, returns only the columns you list and can group and count records in one statement. That makes it the natural tool for audits, data cleanup and troubleshooting. A question like "which active users have no direct assignment of this permission set" takes one statement instead of an export and a lookup.
This guide covers the syntax, ten queries you can adapt, the errors you will meet first and what a query can and cannot see. If you would rather describe the question in plain English, the Cirra AI Salesforce Admin MCP Server lets your AI client write and run the query for you. Knowing the language still pays off, because it lets you read the query your AI shows you before you trust the answer.
SOQL, reports and SOSL: when each one fits
SOQL fits when you know which object holds the data. Salesforce's documentation says it suits retrieving data from one object or from related objects, counting records that match criteria and sorting results inside the query. SOSL is the other query language. The documentation describes it as a text-based search against the search index, and it fits when you do not know which object or field holds the term you are looking for.
Use a report when the audience is a business user who needs a chart or a schedule. Use SOQL when the audience is you and the question is about the structure or state of the data: which records break a rule, which users hold a permission, how many records leave a field empty.
Where admins can run a SOQL query
You have four common options, and the query text is the same in all of them.
- Developer Console. The Query Editor tab runs a query and shows the rows in a grid. It needs no installation, which makes it the easiest place to start.
- Salesforce CLI. The
sf data querycommand takes the query in its--queryflag and the org in its--target-orgflag. - A browser extension. Salesforce Inspector Reloaded is popular with admins, and Salesforce Ben's admin guide to SOQL walks through it. Some extensions also let you edit or delete the rows a query returns, so treat those buttons as write tools.
- Your AI client. With Cirra AI connected, you ask the question in Claude, ChatGPT or Cursor and the query runs against your org.
Run unfamiliar queries in a sandbox first, and put a LIMIT on anything you have not run before.
sf data query --query "SELECT Name, Industry FROM Account LIMIT 5" --target-org my-sandbox
The anatomy of a SOQL query
Here is a complete query with every clause an admin uses daily.
SELECT Id, Name, Industry
FROM Account
WHERE Industry = 'Technology'
ORDER BY Name
LIMIT 10
SELECT lists the fields to return, separated by commas. FROM names the object. WHERE filters the rows. ORDER BY sorts them, ascending by default, and you add DESC to reverse the order. LIMIT caps how many rows come back. In the statement, the clauses always appear in this order: SELECT, FROM, WHERE, GROUP BY, HAVING, ORDER BY, LIMIT.
Two details cause most beginner errors. SOQL uses API names, never field labels, so "Annual Revenue" is AnnualRevenue and a custom field ends in __c. Text values sit inside single quotes, and double quotes fail.
Operators and date literals worth memorizing
| Operator | What it does | Example |
|---|---|---|
| = and != | Exact match, or not equal | StageName = 'Closed Won' |
| <, <=, >, >= | Compare numbers and dates | Amount >= 10000 |
| LIKE | Pattern match, with % as the wildcard | Name LIKE 'Acme%' |
| IN and NOT IN | Match a list of values, or the result of a subquery | StageName IN ('Prospecting', 'Qualification') |
| INCLUDES and EXCLUDES | Match values in a multi-select picklist | Interests__c INCLUDES ('Golf') |
| = null | The field is empty | Industry = null |
| AND, OR, NOT | Combine conditions, with parentheses to control order | IsClosed = false AND Amount > 0 |
Date literals save you from typing dates. TODAY, THIS_MONTH and THIS_QUARTER describe a calendar period. LAST_N_DAYS:30 starts at midnight 30 days before today and runs to the current moment, so it includes today. LAST_N_MONTHS:3 starts at the first day of the month that began three months before the current month. Salesforce documents the full list in its SOQL date format and date literals reference.
Ten SOQL queries admins can adapt
Each query below answers a question that comes up in real admin work. Swap in your own object, field and permission set names.
1. Open opportunities closing this quarter
SELECT Name, Amount, StageName, CloseDate, Owner.Name
FROM Opportunity
WHERE IsClosed = false AND CloseDate = THIS_QUARTER
ORDER BY Amount DESC
LIMIT 50
Owner.Name reaches from the Opportunity to its owner. That dot notation is a child-to-parent relationship, and the next example uses it across two levels.
2. Contacts with their account and the account owner
SELECT Name, Email, Account.Name, Account.Owner.Name
FROM Contact
WHERE Account.Industry = 'Technology'
You can filter on a parent field in the WHERE clause as well as select it. On a custom lookup field, the relationship name ends in __r instead of __c, so a lookup called Region__c is reached as Region__r.Name.
3. Accounts with their open opportunities
SELECT Name,
(SELECT Name, Amount FROM Opportunities WHERE IsClosed = false)
FROM Account
LIMIT 20
A subquery in parentheses pulls child records alongside each parent. The subquery uses the plural relationship name, Opportunities, rather than the object name. This is the parent-to-child direction.
4. Active users without a direct permission set assignment
SELECT Id, Name, Profile.Name
FROM User
WHERE IsActive = true
AND Id NOT IN (
SELECT AssigneeId FROM PermissionSetAssignment
WHERE PermissionSet.Name = 'Sales_Operations'
)
Replace Sales_Operations with the API name of your permission set. The inner query lists the users who have it assigned directly, and NOT IN keeps everyone else. This is a direct-assignment audit: a user who receives the same access through a permission set group still shows up in the results, so check group membership before you remove or reassign anything. For more on this kind of audit, see auditing Salesforce metadata without a developer.
5. Leads nobody has touched in a year
SELECT Id, Name, Company, LastModifiedDate
FROM Lead
WHERE IsConverted = false AND LastModifiedDate < LAST_N_DAYS:365
ORDER BY LastModifiedDate
LIMIT 200
Use this before a cleanup so you review the list instead of deleting by guesswork.
6. Pipeline by stage
SELECT StageName, COUNT(Id), SUM(Amount)
FROM Opportunity
WHERE IsClosed = false
GROUP BY StageName
COUNT and SUM are aggregate functions, and GROUP BY collapses the rows into one line per stage. Every field in the SELECT list must either be an aggregate or appear in the GROUP BY clause.
7. Duplicate email addresses on contacts
SELECT Email, COUNT(Id)
FROM Contact
WHERE Email != null
GROUP BY Email
HAVING COUNT(Id) > 1
WHERE filters rows before they are grouped. HAVING filters the groups afterward, which is why it can use COUNT.
8. Which permission sets and profiles grant access to a field
SELECT Parent.Label, Parent.Profile.Name, PermissionsRead, PermissionsEdit
FROM FieldPermissions
WHERE SobjectType = 'Account' AND Field = 'Account.AnnualRevenue'
FieldPermissions stores the field permissions granted through each parent permission set. Each profile has a matching permission set behind the scenes, which is why Parent.Profile.Name can identify the profile. Rows with PermissionsEdit set to false are read-only entries. This query confirms a field-level security change landed where you intended. It shows what is granted, not which users end up with edit access.
9. How many records leave a field empty
SELECT COUNT()
FROM Account
WHERE Industry = null
A count by itself returns a number and no rows. Swap in a custom field to see whether it earns its place on the page layout.
10. Explore an object you do not know
SELECT FIELDS(STANDARD)
FROM Contact
LIMIT 5
FIELDS(STANDARD) returns every standard field you can access. FIELDS(CUSTOM) and FIELDS(ALL) work too, but Salesforce requires a LIMIT of 200 or less on them in the CLI and the REST and SOAP APIs. The syntax is documented in the SOQL SELECT reference.
Common SOQL errors and how to fix them
No such column. Check the API name first. The label you see on a page layout is rarely the API name, and custom fields need the __c suffix. The same message also appears when the field exists but your field-level security hides it from you, so confirm your own access before you decide the field is missing.
Unexpected token or malformed query. Look for double quotes around text, a missing comma between fields or a clause out of order.
A relationship name that does not resolve. Child-to-parent uses the singular name with a dot, such as Account.Name. Parent-to-child uses the plural relationship name inside a subquery. Custom relationships end in __r.
An aggregate error. Every non-aggregate field in the SELECT list has to appear in GROUP BY. Filter on aggregates with HAVING, never WHERE.
FIELDS(ALL) without a LIMIT. Add LIMIT 200 or lower, or switch to FIELDS(STANDARD).
Zero rows when you expected some. Check the filter values and spelling first. Then check what the running user can see. Field-level security and sharing apply to the person who runs the query.
What a query can see, and safe habits
Your results depend on who runs the query. Salesforce's documentation states that FIELDS() respects field-level security, so it returns only the fields you can access. When Salesforce recommends enforcing permissions in code, it points to the WITH USER_MODE clause, which applies the running user's field-level security and object permissions along with sharing rules.
Three habits keep queries safe. Test in a sandbox before you build anything on a result. Add a LIMIT while you are still learning what an object holds. Keep read tools and write tools separate in your head, since a query returns data and a button beside the results may change it.
Large extracts need a different path. Salesforce designed Bulk API 2.0 query jobs for queries that return 2,000 records or more, and Cirra AI includes a bulk query tool built on that API.
Using AI to write SOQL, and how to check what it wrote
SF Ben's 2026 Salesforce Admin Survey found that about 44% of respondents now use AI daily or regularly. For SOQL, an AI client gives you a useful first draft, and you remain the person who signs off on it.
- Describe the question in plain English and name the object, for example "list active users with no direct Sales_Operations permission set assignment."
- Ask the AI to show the SOQL it ran.
- Read the query against the anatomy above: the object in FROM, the fields in SELECT, the filters in WHERE.
- Run it in a sandbox and compare the row count with what you expect.
- Save the queries you reuse, so the next audit starts from a tested statement.
Cirra AI connects your Salesforce org to the AI client you already use, over OAuth, and it runs as you, within your permissions. A request that only reads data uses 1 credit. The Free plan includes 100 credits a month with no credit card required, and Cirra AI supports Salesforce Enterprise Edition and up. The Connect Claude to Salesforce guide covers setup, Cirra AI for Salesforce admins shows what else it handles, and the checklist for letting AI change your org covers the governance questions worth settling first.
The queries in this article follow Salesforce's documented SOQL syntax. Object and field names are standard, but results depend on your org's data and permissions, so run each query in a sandbox before you rely on it. Ready to try it on your own org? Choose Start Free Trial, or Book a Demo to walk through your own queries with us.
Frequently asked questions
What is SOQL used for in Salesforce?
SOQL retrieves records from your org. Admins use it for audits, data cleanup, troubleshooting and any question that a report type cannot reach, such as which users hold a permission or how many records leave a field empty.
Do Salesforce admins need to learn SOQL?
You can do admin work without it, but a small amount of SOQL pays off. Six clauses cover most daily questions: SELECT, FROM, WHERE, ORDER BY, LIMIT and GROUP BY. Reading a query is an even smaller step, and it lets you check any query an AI client writes for you.
What is the difference between SOQL and SOSL?
SOQL queries specific objects and fields when you know where the data lives. SOSL is a text-based search against the search index, and it fits when you do not know which object or field holds a term. Most admin questions are SOQL questions.
Can SOQL update or delete records?
No. SOQL only retrieves data. Updating or deleting records takes another tool, such as a flow, Data Loader or Apex. Some query tools add edit and delete buttons beside the results, so check what a button does before you click it.
How do I run a SOQL query without writing code?
Open the Query Editor in the Developer Console, use a browser extension such as Salesforce Inspector Reloaded, or describe the question to an AI client connected to your org. In every case you can read the query before you run it.
Why does my SOQL query say "No such column"?
The field name is usually wrong. Use the API name rather than the label, and add __c to custom fields. The message also appears when field-level security hides an existing field from your user, so check your access if the name is correct.
Can AI write SOQL queries for me?
Yes. An AI client connected to your org can turn a plain-English question into a query and run it. Ask it to show the SOQL, read it against the syntax in this article and test it in a sandbox first.


