This article is relevant if you can run standard NetSuite financial reports, but you still find yourself (or your Controller) exporting transaction detail to a spreadsheet to explain why a balance sheet account balance is “reasonable” at period close.
TL;DR Summary
Balance sheet explanations are easiest when you treat the General Ledger as a filtered view of the transaction table: posted lines, summed cumulatively from inception through an end date (or period). Build saved searches and SuiteQL queries around that model. Use (1) a posting-only, no-start-date pattern for balance sheet accounts, (2) entity groupings to explain who the balance belongs to, and (3) period-to-period comparisons that compute two cumulative balances and subtract them. This approach reduces spreadsheet dependency and increases trust in your accounting period close review.
Background
Our firm frequently works with two groups who are both competent, but who learned the system from different sides:
- NetSuite Administrators who can configure records and workflows, but do not have deep financial accounting training.
- Accounting Controllers who understand the balance sheet deeply, but have limited experience building saved searches or writing queries.
NetSuite’s financial reports and drill-downs are very good. Still, during a close, Controllers are often asked to explain balance sheet balances in plain terms: “What is this made of, and does it look reasonable?” The classic example is Accounts Receivable. Nobody explains A/R by staring at the trial balance; they go to the A/R Aging, which groups balances by customer. That breakdown is the explanation. The same expectation applies to many other accounts (customer deposits, accrued liabilities, inventory accounts, inventory received not billed (purchase accruals)}, clearing accounts, and more).
Explaining Balance Sheet Movement Without Leaving NetSuite
Changes in balance sheet values are also an explanation tool. If the ending balance moved materially from one period to the next, you want to see what changed and why. Many accountants are accustomed to downloading all transaction details to build pivots and filters in a spreadsheet. That works, but it misses a key advantage of NetSuite: the system already contains the relational model and the time dimension that produces financial statements. If you can query it properly, you can answer questions faster, with fewer manual steps, and with better auditability.
The foundational insight is simple and unlocks a world of potential: the general ledger is effectively the Transaction table where the Posting flag is on (or ‘T’ or True).
Downloads and Previous Article References for Insight and Learning
In 2019, I wrote an article to help Administrators learn how to craft better financial saved searches. It is still a great “mind opener” to get grounded in how NetSuite expresses financial truth through its database model: Learn How To Craft Better NetSuite Financial Saved Searches.
Over the years, I have also written several related articles that lean on the same fundamentals, and we share a Financial Saved Search Library with end users (for the asking) to help teams accelerate learning and standardize analysis:
- 2016: How to Produce a NetSuite Trial Balance with Saved Searches
- 2016: How To: NetSuite Stock Inventory Movement and In-Transit
- 2017: Explaining NetSuite’s Inventory Received Not Billed Account
- 2018: Learn How To Accumulate NetSuite Inventory Balances via Saved Search
- 2021: Get a NetSuite Accounts Receivable with Customer Deposit Aging
NetSuite Balance Sheet Searches: Two Concepts That Prevent Mistakes
Hold these two ideas when you build your searches:
- Balance sheet accounts are cumulative from inception: If you want to explain a balance sheet number, you need a transaction posting search with no start date, and an end date (or period end boundary). This is the opposite of how most teams naturally query income statement accounts, which are usually summarized within a fiscal year or within a specific period range.
- Transaction dates are not the same thing as accounting periods: Financial statements are most frequently and reliably expressed by accounting period. NetSuite stamps posting lines with an accounting period, and that period drives financial reporting. Depending on the configuration, transaction dates may fall outside the accounting period. That may be perfectly acceptable. But it is easy to trip over. If your question is financial, your time dimension should usually be the accounting period, not the transaction date.
These two ideas explain why some saved searches “look right” but quietly disagree with the trial balance, the balance sheet, or the period close process. When you build balance sheet explanations, you are not trying to find “activity in a month.” You are trying to explain “the cumulative balance as of a close boundary,” and then optionally compare two close boundaries to understand the change.
Remember, when building any search or query, always make sure that the results tie out to NetSuite’s built-in financial statements.
Two Key Balance Sheet Saved Search Patterns
I included two screenshots here that demonstrate the recurring pattern from my 2016 trial balance article:
- Criteria screenshot: Posting = true; include safeguards such as showing inactive accounts or highlighting rare problematic accounts.
- Results screenshot: Use Summary (grouping) and formulas that sum Debit Amount ({debitamount}) and Credit Amount ({creditamount}) to compute a net balance; include a time boundary using transaction date cautiously, or preferably accounting period logic where appropriate.
Click the images to see them full-screen.
Finally, consider my 2016 article to deepen your understanding: How to Produce a NetSuite Trial Balance with Saved Searches.
A Practical Approach: Saved Searches First, Then SuiteQL (With Better Prompts)
In 2026, we have more options than we did a few years ago. Natural language models can accelerate the time to a Controller or Administrator’s first draft of a query. SuiteQL rewards those who learn it, and on our team, everyone is conversant because it extends what NetSuite can do without purchasing add-on tools or building a data warehouse.
That said, the tools are not perfect. They get you close, but they often get details wrong, and the query may not run without edits. The value is speed-to-start, not guaranteed correctness. Competence still comes from understanding the model and mechanics.
Here is an example prompt that creates a strong starting point for balance sheet account analysis (using GL account 2101, Customer Deposits, as the example):
Example AI Prompt for SuiteQL Assistance
I’m working in NetSuite and need help writing SuiteQL queries for balance sheet account analysis.
Important context: Account 2101 is a balance sheet account (Asset/Liability/Equity), which means balances are cumulative from inception.
- Basic query: Show the current total balance.
- By entity: Break down by customer/vendor.
- Period comparison: Compare two period-end balances and calculate the change.
Reminder: Balance sheet accounts require cumulative logic through each period end date.
From there, you refine toward something that will run in your account and match your reporting logic. If you want to make SuiteQL accessible to more end users, we also provide license-free tools to our clients that render NetSuite SQL queries like saved searches. See our 2021 debut of Render NetSuite SQL Queries Like Saved Searches.
Insight: Three SuiteQL Building Blocks for Balance Sheet Explanations
I will use “Customer Deposits” (GL account 2101) as a concrete general ledger liability account example. The goal is not to memorize these; it is to learn the pattern and reuse it for any balance sheet account.
1) Basic pattern: balance for a balance sheet account
What it does: sums all posted transaction lines to account 2101; debits are positive and credits are negative. Tie this directly to your balance sheet as of now.
-- 1) Net balance for GL Account 2101 (Customer Deposits)
SELECT
a.acctNumber,
a.accountSearchDisplayNameCopy AS accountName,
SUM(tal.amount) AS balance
FROM
TransactionAccountingLine tal
INNER JOIN Account a ON tal.account = a.id
WHERE
a.acctNumber = '2101'
AND tal.posting = 'T'
GROUP BY
a.acctNumber,
a.accountSearchDisplayNameCopy
2) Explanation pattern: break the balance out by entity
What it does: shows which customers (or other entities) “make up” the balance; helps detect oddities like journal entries impacting the account, net debit balances in a liability account, or lines with no entity association. Here, we are using group concepts to bring for the explanation.
-- 2) Balance by entity for GL Account 2101
SELECT
a.acctNumber,
a.accountSearchDisplayNameCopy AS accountName,
e.id AS entityId,
e.entityId AS entity,
SUM(tal.amount) AS balance
FROM
TransactionAccountingLine tal
INNER JOIN Account a ON tal.account = a.id
INNER JOIN Transaction t ON tal.transaction = t.id
LEFT JOIN Entity e ON t.entity = e.id
WHERE
a.acctNumber = '2101'
AND tal.posting = 'T'
GROUP BY
a.acctNumber,
a.accountSearchDisplayNameCopy,
e.id,
e.entityId
HAVING SUM(tal.amount) <> 0
ORDER BY
balance ASC
3) Period comparison: two cumulative balances, then subtract
The key concept: do not treat this as “transactions in P12.” For balance sheet accounts, compute cumulative balances through each period end boundary, then subtract to get the change. The powerful technique here is to embed period logic into result expressions, rather than filtering the entire query to a single period. Further, we show the build-up of queries that can be passed to the next query, which allows expansion of thinking and capability. Given the complexity, I offer more embedded comments to help educate.
-- ============================================================================
-- GL Account Balance Comparison by Entity Between Two Periods
-- ============================================================================
-- Purpose: Calculate the ending balance for GL Account 2101 by entity (customer)
-- at the end of two accounting periods and show the change between them.
--
-- Balance Sheet Logic: For balance sheet accounts, balances are CUMULATIVE from
-- inception through the period end date (not just transactions within
-- the period).
--
-- Parameters to modify:
-- - Account Number: Change '2101' to analyze different GL accounts
-- - Period Names: Change 'P11 2025' and 'P12 2025' to compare different periods
-- ============================================================================
-- Step 1: Get the end dates for the two periods we're comparing
WITH PeriodDates AS (
SELECT
-- Extract the end date for period 1 (P11 2025)
MAX(CASE WHEN periodName = 'P11 2025' THEN endDate END) AS p11_endDate,
-- Extract the end date for period 2 (P12 2025)
MAX(CASE WHEN periodName = 'P12 2025' THEN endDate END) AS p12_endDate
FROM AccountingPeriod
WHERE periodName IN ('P11 2025', 'P12 2025')
),
-- Step 2: Calculate cumulative balances for each entity at each period end
EntityBalances AS (
SELECT
a.acctNumber,
a.accountSearchDisplayNameCopy AS accountName,
e.id AS entityId,
e.entityId AS entity,
-- Period 1 ending balance: Sum ALL transactions from inception through P11 2025 end date
-- This gives us the balance sheet balance as of the last day of P11 2025
SUM(CASE
WHEN t.tranDate <= pd.p11_endDate
THEN tal.amount
ELSE 0
END) AS p11_balance,
-- Period 2 ending balance: Sum ALL transactions from inception through P12 2025 end date
-- This gives us the balance sheet balance as of the last day of P12 2025
SUM(CASE
WHEN t.tranDate <= pd.p12_endDate
THEN tal.amount
ELSE 0
END) AS p12_balance
FROM
-- TransactionAccountingLine contains the GL impact of each transaction
TransactionAccountingLine tal
-- Join to Account to filter by account number and get account details
INNER JOIN Account a ON tal.account = a.id
-- Join to Transaction to access transaction date
INNER JOIN Transaction t ON tal.transaction = t.id
-- Left join to Entity to get customer/vendor/employee details
-- (some transactions may not have an entity)
LEFT JOIN Entity e ON t.entity = e.id
-- Cross join to get the period end dates we calculated above
-- (this adds p11_endDate and p12_endDate to every row for comparison)
CROSS JOIN PeriodDates pd
WHERE
-- Filter to the specific GL account we want to analyze
a.acctNumber = '2101'
-- Only include posting transactions (exclude non-posting)
-- posting = 'T' means the transaction impacts the GL
AND tal.posting = 'T'
-- IMPORTANT: We do NOT filter by posting period here because we need
-- ALL transactions from inception to calculate cumulative balances
GROUP BY
a.acctNumber,
a.accountSearchDisplayNameCopy,
e.id,
e.entityId
)
-- Step 3: Display the results with meaningful column names and calculate the change
SELECT
acctNumber,
accountName,
entityId,
entity,
-- Show the cumulative balance at the end of period 1
p11_balance AS "P11 2025 Ending Balance",
-- Show the cumulative balance at the end of period 2
p12_balance AS "P12 2025 Ending Balance",
-- Calculate the change (this represents activity between the two period end dates)
p12_balance - p11_balance AS "Change (P11 to P12)"
FROM
EntityBalances
WHERE
-- Only show entities where the balance actually changed
-- (excludes entities with no activity between the periods)
p12_balance - p11_balance != 0
ORDER BY
-- Sort by largest absolute change first (regardless of whether it's positive or negative)
ABS(p12_balance - p11_balance) DESC
Key Search and SuiteQL Implementation Considerations
- Use posting-only lines for financial truth. If your goal is to explain a GL balance, start from the transaction lines that are posting. This keeps your results aligned with the balance sheet and trial balance logic.
- Model balance sheet time as “through” a boundary. Balance sheet accounts are, by definition, inception-to-date. Your filter design should reflect that, even when you are comparing two periods. This can be tricky because NetSuite’s filtering systems want to expose the start date, which will break your balance sheet, as you must start from inception (no start date).
- Prefer Accounting Period for financial questions. The transaction date can be informative operationally, but the accounting period is the backbone of financial reporting. If you mix them casually, you can produce results that are accurate in isolation but wrong for the close.
- Group by entity to create an explanation, not just a number. The entity breakdown is often the quickest reasonableness test. It surfaces concentrated balances, missing entities, and posting patterns that do not match the business story.
- Expect iteration when using natural language tools. Treat AI-generated queries as a first draft. While we all expect this to get better, your fundamental competence will make the difference in how much time you save using these tools.
Building Accounting Period Close Confidence Through Fundamental Modeling
Fundamentals are the key to working with business systems. NetSuite’s expression of the balance sheet is elegant because it is simple: posted transaction lines, summarized through an accounting period boundary, grouped into accounts. Once you internalize that model, saved searches and SuiteQL become two different ways to express the same truth.
When we work with clients, we stay grounded in these fundamentals so we can listen well, understand ambitions, and then build capabilities that leverage the platform without limiting creativity and insight. In practice, that means reusable saved searches, query patterns that reconcile cleanly, and license-free utilities and algorithms that make teams faster without adding tool sprawl. As mentioned, if you are an end user, reach out with your NetSuite account ID to obtain the Financial Saved Search Library.
If you found this article relevant, feel free to sign up for notifications to new articles as I post them. If you are ready to build close-ready balance sheet explanations directly in NetSuite (without living in spreadsheets), let’s have a conversation.


Thanks Marty for writing on this topic. Taking AI assistance to generate SquiteQL for Balance Sheet, is definitely a smart approach. We had a requirement to create a multi-column Balance Sheet, as mentioned in: https://4146758.app.netsuite.com/app/help/helpcenter.nl?fid=section_n2102164.html
Our period range was more than 30 and it hit the NS limitation of 30 columns for a report.
Using a Squite QL in a scheduled script, we were able to create the report. Importantly, report was created in few mins, in comparison the close to an hour taken by the inbuilt NS report engine for a multi-column BS.
BR
Veda.
Thank you Veda,
The reminder of NetSuite report output challenges are valuable to know that we can overcome them. One more reason we love the platform.
Marty