NetSuite top customers by revenue: building a report that holds up
Build a top customers by revenue report in NetSuite, and see why revenue, invoiced and collected give three different rankings of the same customers.
A top customers by revenue report in NetSuite is either the Sales by Customer summary report or a transaction saved search grouped by customer with amount summed, ranked descending over a date range. The ranking changes depending on whether you sum invoiced totals, posted income accounts or cash collected — decide which one you mean before publishing it.
Key takeaways
- Invoiced, recognised and collected revenue give three different top-10 lists. Name the one you mean in the report title, not in a footnote.
- Sales orders don't post. If a sales-side report includes them alongside invoices, every order you've billed is counted twice.
- Cash sales are revenue. A report filtered to Type = Invoice quietly deletes your entire retail or web channel from the ranking.
- Summing income-account accounting lines is the only definition that agrees with the income statement, because it ignores tax, freight and non-posting documents by construction.
- Rank by margin as well as revenue. The customer at the top of the revenue list is often third or fourth once you strip the cost of serving them.
"Who are our top ten customers?" sounds like a two-minute request. It becomes a forty-minute request the moment two people produce two different lists, which is the normal outcome, because NetSuite can answer the question in at least three defensible ways. Here is the same customer for the first half of 2026, measured three ways:
None of those is wrong. The $164,580 gap between invoiced and revenue is sales tax, freight recharges and a credit memo; the gap between revenue and collected is just terms. But if the sales director's deck uses invoiced and the CFO's uses posted revenue, the ranking will differ and you will spend the meeting on arithmetic instead of customers.
Revenue, invoiced or collected: pick one and label it
| Definition | How it's built in NetSuite | Use it for | Watch out for |
|---|---|---|---|
| Invoiced | Sum of transaction totals on invoices and cash sales, less credit memos | Sales performance and commission | Includes tax and freight, so it will never tie to the income statement |
| Recognised revenue | Sum of accounting lines posted to income accounts | Anything a finance leader will see | Deferred revenue and rev-rec schedules shift it into other periods |
| Collected | Customer payments applied in the period | Cash forecasting and collections priority | Payments applied to prior-period invoices distort the current ranking |
| Gross margin | Income lines less the COGS lines on the same transactions | Deciding who deserves attention | Only as good as your item costing; landed cost is often missing |
The native report, and what it assumes
NetSuite's Sales report category includes a Sales by Customer pair — summary and detail — which is the fastest route to a ranked list. Set the date range, sort descending on amount, and you have something usable in under a minute. Before you send it, check three things.
- What the amount column contains. Sales reports are built around transaction amounts, which can include shipping and tax depending on how your items and reports are configured. Your income statement contains only what posted to income accounts. If the two totals differ by a suspiciously round percentage, that's usually tax.
- Whether the date range means transaction dates or posting periods. There is an accounting preference that controls whether reports are driven by posting period or by transaction date, and it can apply to financial reports only. When it does, your sales report uses transaction dates while your income statement uses periods — which is precisely how one invoice dated 31 March and posted in April makes two reports disagree.
- Which subsidiaries are in scope. In OneWorld, the subsidiary context you're in and the consolidation you display both change the answer. A consolidated ranking translates child-subsidiary amounts at a rate, so a customer trading in two currencies can move several places purely on FX.
The saved search version
When you need customer fields the report doesn't carry — segment, region, account manager, credit terms — build it as a transaction saved search. The recipe is short:
- 1.Criteria: Posting is true. Type is any of Invoice, Cash Sale, Credit Memo, Cash Refund. Date is within your range. Main Line is true if you are summing the transaction total, and false if you are summing line amounts — mixing the two double-counts everything.
- 2.Results: Customer (group), Amount (sum), and Amount grouped by period if you want the trend beside the total.
- 3.Sort: descending on the summed amount. Saved searches don't take a
TOP 10— you sort and read the first ten rows, or add a criterion on summed amount if you genuinely need to cut the list short. - 4.Then add the fields the report couldn't give you: customer category, sales rep, terms, or a custom field on the customer record. This is the entire reason to be in a saved search rather than a report.
Take the revenue and COGS for your top account and see what the margin actually is before you decide it's your best customer.
The SuiteQL version
For the definition that ties to the income statement, go through the accounting lines rather than the transaction totals. This is the query worth keeping, because it can't accidentally include tax, freight or a non-posting order:
SELECT * FROM (
SELECT
c.entityid AS customer,
ROUND(SUM(tal.credit) - SUM(tal.debit), 2) AS net_revenue
FROM transactionaccountingline tal
JOIN transaction t ON t.id = tal.transaction
JOIN account a ON a.id = tal.account
JOIN customer c ON c.id = t.entity
WHERE a.accttype = 'Income'
AND tal.posting = 'T'
AND t.trandate BETWEEN TO_DATE('2026-01-01', 'YYYY-MM-DD')
AND TO_DATE('2026-06-30', 'YYYY-MM-DD')
GROUP BY c.entityid
ORDER BY net_revenue DESC
) WHERE ROWNUM <= 10Three notes on that query. Income is a credit balance in the ledger, so revenue is credits minus debits — get the sign backwards and your worst-returning customer tops the list. If you run multiple accounting books, add a filter on the accounting book column or you will sum every book together. And swapping the trandate range for a posting-period filter is what makes this agree with the balance-sheet-driven reports; the accountingperiod table holds quarter and year rollup rows as well as months, so filter to base periods when you build that list. If your saved queries have degenerated into single-line strings, the SuiteQL formatter will make them readable again.
Parent and child customers
This is the trap that produces a genuinely wrong answer rather than a differently-defined one. If your account uses customer hierarchies — one parent with a subsidiary or store per child record — transactions post against the child. Group by the transaction's entity and a $4.2M group appears as eleven separate $380,000 customers, none of which makes the top ten. Roll up through the customer record's parent field:
SELECT
COALESCE(BUILTIN.DF(c.parent), c.entityid) AS customer_group,
ROUND(SUM(tal.credit) - SUM(tal.debit), 2) AS net_revenue
FROM transactionaccountingline tal
JOIN transaction t ON t.id = tal.transaction
JOIN account a ON a.id = tal.account
JOIN customer c ON c.id = t.entity
WHERE a.accttype = 'Income'
AND tal.posting = 'T'
GROUP BY COALESCE(BUILTIN.DF(c.parent), c.entityid)
ORDER BY net_revenue DESCReading the ranking
A ranked list on its own is trivia. Three things make it a decision.
- Concentration. Add a cumulative percentage column. If your top 5 customers are more than half of revenue, that number belongs in the board pack and in your bank covenant conversations. The same Pareto arithmetic applied to items instead of customers is what the ABC analysis calculator does.
- Movement, not level. Rank this period against the same period last year, in the same query. The interesting rows are the ones that moved four places, in either direction. A customer sliding from 3rd to 9th is a churn conversation you would otherwise have next quarter.
- Why revenue moved. "Revenue up 6%, margin down 2 points" is almost always mix. Decomposing it into price, volume and mix effects takes ten minutes with the price volume mix calculator, and price volume mix analysis walks through a worked example.
- Margin per customer, not revenue per customer. Once you have income and COGS lines from the same transactions, the ranking changes shape. The mechanics of getting cost onto those lines properly are in the NetSuite item profitability report.
Or skip the build
The report is not hard. Agreeing on the definition, remembering the credit memos, rolling up the hierarchy and re-running it for a different period next week is what actually costs time. Ask "top 10 customers by posted revenue for H1, rolled up to parent, with margin" and you get the number computed live from your own NetSuite account with the SuiteQL shown underneath — so the definition is on screen instead of in someone's head.
Frequently asked questions
How do I get a top 10 customers report in NetSuite?
Run the Sales by Customer summary report for your date range and sort descending on amount, or build a transaction saved search grouped by customer with amount summed and sorted descending. Saved searches have no TOP N clause — you sort and read the first ten rows. In SuiteQL, wrap an ordered subquery and filter on ROWNUM.
Why does my NetSuite revenue by customer report not match the income statement?
Most often because the customer report sums transaction totals, which include sales tax and freight, while the income statement sums only what posted to income accounts. The second cause is date basis: sales reports may run on transaction date while financials run on posting period, so documents dated at a month boundary land in different periods.
Should cash sales be included in a top customers by revenue report?
Yes, if they represent real revenue for you. A cash sale posts income just as an invoice does; it simply skips accounts receivable. Filtering to Type = Invoice removes your entire retail, POS or web channel from the ranking, which is a common and silent error in NetSuite sales searches.
How do I roll subsidiary customers up to the parent in NetSuite reporting?
Transactions post against the child customer record, so group on the parent instead. In a saved search, use the customer's parent field as the summary field; in SuiteQL, join the customer table and group on COALESCE of the parent's name and the customer's own name. Without this, one large group appears as several mid-sized customers.
What is the difference between invoiced and recognised revenue in NetSuite?
Invoiced is the total you billed, including tax and freight, on the date you billed it. Recognised revenue is what posted to income accounts, which for anything with a revenue recognition schedule is spread across future periods. If you sell subscriptions or multi-element contracts, the two numbers can differ substantially for the same customer.
Calculators for this
Calculate gross margin from revenue and COGS. Get gross profit, margin %, markup %, margin per unit, and the price you need for a target margin.
Split a revenue change into price, volume and mix effects across up to five product lines. The three effects reconcile exactly to the total variance.
Paste item values and run an ABC analysis: Pareto ranking, cumulative percentage, and A/B/C classes with your own thresholds, plus value per class.
Calculate contribution margin per unit and as a ratio, split contribution across product lines, and see which line to push against a capacity constraint.
Keep reading
Price volume mix analysis with a fully worked example: an additive decomposition where price, volume and mix sum exactly to the revenue change.
Build a NetSuite item profitability report that ties out: estimated versus actual COGS, landed cost allocation, and why item margin never equals GL margin.
The real ceilings of NetSuite saved searches: join depth, summary maths, row limits and performance, plus the right tool to use for each one.
Why NetSuite custom fields disappear from reports: store value, applies-to, field type and role access, plus how to query custbody and custcol fields.