How to Get Total Net Sales in NetSuite Using SuiteQL: A Complete Guide
Understanding the Challenge
How to Get Total Net Sales in NetSuite Using SuiteQL: A Complete Guide

Understanding the Challenge
If you’ve ever tried to reconcile NetSuite’s Income Statement with your transaction data, you know it can be frustrating. The numbers don’t always match up the way you’d expect. Why? Because NetSuite’s income statement often shows gross sales before discounts, while your transaction queries might be pulling different data.
Today, I’ll show you how to use SuiteQL to get accurate net sales figures that match your financial statements.
What is SuiteQL?
SuiteQL is NetSuite’s SQL-like query language that allows you to directly query your NetSuite database. Unlike saved searches, SuiteQL gives you the flexibility of SQL with JOINs, aggregations, and complex logic — perfect for financial reporting.
The Problem: Why Simple Transaction Queries Don’t Work
Your first instinct might be to query transactions directly:
-- This seems logical but won't give you the full picture
SELECT SUM(foreigntotal)
FROM transaction
WHERE type IN ('CustInvc', 'CashSale')
But this approach misses crucial details:
- Credit memos that reduce revenue
- Vendor bills that might credit sales accounts (rebates)
- Deposits for chargebacks won
- Discounts applied at various levels
- Non-sales transactions affecting income accounts
The Solution: Query the Transaction Accounting Lines
The key to accurate financial reporting in NetSuite is understanding that every transaction creates accounting lines — the actual debits and credits that hit your general ledger. Here’s the query that gets it right:
/* Total Net Sales for any period */
SELECT
'NET SALES' AS Description,
SUM(COALESCE(TransactionAccountingLine.Credit, 0) -
COALESCE(TransactionAccountingLine.Debit, 0)) AS TotalNetSales
FROM
Transaction
INNER JOIN TransactionAccountingLine
ON TransactionAccountingLine.Transaction = Transaction.ID
INNER JOIN Account
ON Account.ID = TransactionAccountingLine.Account
WHERE
Transaction.Posting = 'T' -- only posting transactions
AND TransactionAccountingLine.Posting = 'T' -- only posting GL lines
AND Account.AcctType = 'Income' -- Income accounts only
AND Transaction.TranDate BETWEEN TO_DATE('2025-06-01','YYYY-MM-DD')
AND TO_DATE('2025-06-30','YYYY-MM-DD')
Breaking Down the Query
Let’s understand each component:
1. The Tables We’re Joining
Transaction: The header record for all transactionsTransactionAccountingLine: The actual GL impact of each transactionAccount: The chart of accounts
2. Why TransactionAccountingLine is Critical
This table contains the actual debits and credits that hit your general ledger. It captures:
- Sales from invoices and cash sales
- Reductions from credit memos
- Adjustments from vendor rebates
- Impact of deposits and other non-standard transactions
3. The Posting Filter
Transaction.Posting = 'T' AND TransactionAccountingLine.Posting = 'T'
This ensures we only include transactions that actually affect the GL — no drafts or non-posting entries.
4. The Math
SUM(COALESCE(TransactionAccountingLine.Credit, 0) -
COALESCE(TransactionAccountingLine.Debit, 0))
For income accounts:
- Credits increase income (sales)
- Debits decrease income (returns, discounts)
Getting More Detail: Breaking Down by Account
Want to see which accounts contribute to your net sales? Here’s an expanded version:
SELECT
Account.AcctNumber,
Account.DisplayNameWithHierarchy AS AccountName,
SUM(COALESCE(TransactionAccountingLine.Credit, 0) -
COALESCE(TransactionAccountingLine.Debit, 0)) AS Amount
FROM
Transaction
INNER JOIN TransactionAccountingLine
ON TransactionAccountingLine.Transaction = Transaction.ID
INNER JOIN Account
ON Account.ID = TransactionAccountingLine.Account
WHERE
Transaction.Posting = 'T'
AND TransactionAccountingLine.Posting = 'T'
AND Account.AcctType = 'Income'
AND Transaction.TranDate BETWEEN TO_DATE('2025-06-01','YYYY-MM-DD')
AND TO_DATE('2025-06-30','YYYY-MM-DD')
GROUP BY
Account.AcctNumber,
Account.DisplayNameWithHierarchy
ORDER BY
Account.AcctNumber
This might show you something like:
- 401000 Sales Revenue: $3,246,710.64
- 402000 Freight Income: $17,486.37
- 402510 Sales Discount — Off Invoice: -$504,396.96
- 402500 Sales Discount — On Payment: -$65.97
Including Other Income
Many businesses have other income sources beyond sales. To include these:
SELECT
SUM(CASE WHEN Account.AcctType = 'Income' THEN
COALESCE(TransactionAccountingLine.Credit, 0) -
COALESCE(TransactionAccountingLine.Debit, 0)
ELSE 0 END) AS Sales,
SUM(CASE WHEN Account.AcctType = 'OthIncome' THEN
COALESCE(TransactionAccountingLine.Credit, 0) -
COALESCE(TransactionAccountingLine.Debit, 0)
ELSE 0 END) AS OtherIncome,
SUM(COALESCE(TransactionAccountingLine.Credit, 0) -
COALESCE(TransactionAccountingLine.Debit, 0)) AS TotalRevenue
FROM
Transaction
INNER JOIN TransactionAccountingLine
ON TransactionAccountingLine.Transaction = Transaction.ID
INNER JOIN Account
ON Account.ID = TransactionAccountingLine.Account
WHERE
Transaction.Posting = 'T'
AND TransactionAccountingLine.Posting = 'T'
AND Account.AcctType IN ('Income', 'OthIncome')
AND Transaction.TranDate BETWEEN TO_DATE('2025-06-01','YYYY-MM-DD')
AND TO_DATE('2025-06-30','YYYY-MM-DD')
Common Gotchas and Solutions
1. Gross vs. Net Sales
NetSuite’s income statement might show gross sales with discounts as a separate line. Your query shows net sales (after discounts). To reconcile:
- Check if discount accounts are negative in your Income accounts
- Consider querying discount accounts separately
2. Non-Standard Transactions
Vendor bills crediting sales (rebates), deposits for chargebacks, and journal entries can all affect sales. The TransactionAccountingLine approach captures all of these.
3. Date Considerations
Always use Transaction.TranDate for date filtering, not the date on individual lines. This ensures consistency.
4. Performance Tips
- Always include date ranges to limit data
- Use posting filters to exclude non-GL impacting transactions
- Consider creating a saved search or workbook for frequently-run queries
Implementing in Your Environment
Via SuiteScript:
var sql = `
SELECT SUM(COALESCE(tal.Credit, 0) - COALESCE(tal.Debit, 0)) AS NetSales
FROM Transaction t
INNER JOIN TransactionAccountingLine tal ON tal.Transaction = t.ID
INNER JOIN Account a ON a.ID = tal.Account
WHERE t.Posting = 'T'
AND tal.Posting = 'T'
AND a.AcctType = 'Income'
AND t.TranDate BETWEEN TO_DATE(?, 'YYYY-MM-DD')
AND TO_DATE(?, 'YYYY-MM-DD')
`;
var results = query.runSuiteQL({
query: sql,
params: ['2025-06-01', '2025-06-30']
});
Via Analytics Workbook:
Create a new dataset using the SuiteQL option and paste the query directly.
Conclusion
Getting accurate net sales from NetSuite requires understanding the relationship between transactions, their accounting impact, and your chart of accounts. By querying TransactionAccountingLine instead of just transactions, you capture the complete financial picture — including all the adjustments, discounts, and non-standard entries that affect your revenue.
This approach works for any financial metric: Cost of Goods Sold, Operating Expenses, or any other P&L line item. The key is always to follow the accounting impact through the TransactionAccountingLine table.
Next Steps
- Run this query in your NetSuite environment
- Compare the results with your Income Statement
- Investigate any differences by drilling into specific accounts
- Consider creating saved searches or workbooks for regular reporting
Remember: your financial data tells a story. SuiteQL helps you read it accurately.
Have questions about NetSuite reporting or SuiteQL? Drop a comment below or reach out. Happy querying!
메타데이터
- post_id
- 0e8e25d13384
- slug
- how-to-get-total-net-sales-in-netsuite-using-suiteql-a-complete-guide-0e8e25d13384
- url
- https://medium.com/@suiteprotips/how-to-get-total-net-sales-in-netsuite-using-suiteql-a-complete-guide-0e8e25d13384
- canonical_url
- https://medium.com/@suiteprotips/how-to-get-total-net-sales-in-netsuite-using-suiteql-a-complete-guide-0e8e25d13384
- author_url
- https://medium.com/@suiteprotips
- status
- ok
- fetched_at
- 2026-07-15 07:15:43