Data AnalyticsGenerative AI for verified analyst work

AI-generated SQL: test the query before trusting the explanation

PK
Pankit Kumar
Sr. Data Scientist at Parexel (a Goldman Sachs–backed company) · 20 September 2026 · 3 min read
Technically reviewed by Ishaan Sharma
In this article (6 sections)

SQL can execute successfully and still answer the wrong business question. Before accepting an assistant's explanation, test the query against a metric contract and a fixture with known edge cases: multiple item rows, missing dimension records, boundary dates and status exclusions.

Syntax success is one check. Business correctness requires evidence about grain, eligibility and the resulting values.

Inspect a plausible wrong query

Suppose an assistant proposes the following query for January completed-order amount. This is a deliberately seeded teaching candidate, not a recorded output from a named model.

sql
SELECT COUNT(*) AS rows_counted,SUM(o.order_total_paise) AS amount_paise
FROM orders o JOIN order_items i ON i.order_id=o.order_id
WHERE o.status='completed'
 AND o.ordered_at>='2026-01-01T00:00:00'
 AND o.ordered_at<'2026-02-01T00:00:00';

The query executes, but it counts twelve item-level joined rows and sums repeated order-header amounts to 171,000 paise. The correct order-level population contains eight orders totaling 104,000.

Joining items is not inherently wrong. Summing an order-level value after that join without restoring the intended grain is the error.

Compare execution with an independent reference

The Python example loads the original synthetic commerce database and compares both SQL results with the separate CSV-based calculator used by the analyst-AI lab.

python
import importlib.util
from pathlib import Path
from calculator import calculate

path = Path('../commerce-sql/build_and_verify.py').resolve()
spec = importlib.util.spec_from_file_location('commerce_reference_fixture',path)
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
db = module.database()
parameters = ('2026-01-01T00:00:00','2026-02-01T00:00:00')
wrong = db.execute('''SELECT COUNT(*),SUM(o.order_total_paise)
 FROM orders o JOIN order_items i ON i.order_id=o.order_id
 WHERE o.status='completed' AND o.ordered_at>=? AND o.ordered_at<?''',parameters).fetchone()
correct = db.execute('''SELECT COUNT(*),SUM(order_total_paise) FROM orders
 WHERE status='completed' AND ordered_at>=? AND ordered_at<?''',parameters).fetchone()
db.close()
reference = calculate()
assert wrong==(12,171000)
assert correct==(reference['eligible_order_count'],reference['value'])==(8,104000)
assert wrong!=correct
print({'seeded_wrong_query':wrong,'verified_order_grain_query':correct})

Both paths use the same original teaching fixture, but one calculates directly from CSV source rows while the other executes SQL against its reference database. If either fixture representation changes, reconciliation should fail until the difference is understood.

Test the tempting fixes too

SUM(DISTINCT order_total_paise) is not a general repair. Different orders can have equal amounts, so it removes legitimate values as well as repeated ones. In this fixture it produces 82,000 paise.

An inner customer join creates another problem: the unmatched customer for O1009 causes a valid 9,000-paise order to disappear. That produces 95,000, violating a contract that includes every otherwise eligible order.

The seeded answer cases preserve these failures so a checker can be evaluated against them. They are not evidence of a live model's failure rate.

Separate permission checks from result checks

Run untrusted generated queries only within a suitably restricted environment. This example uses a disposable synthetic in-memory database and executes only the displayed read queries.

A query starting with SELECT is not a complete safety policy, and read access can still expose confidential information or consume excessive resources. A deployed analyst tool needs appropriate data permissions, permitted operations, result limits and resource controls.

Those controls protect the execution boundary. They do not make the query's business logic correct. A read-only query can still double-count orders, use a wrong denominator or infer an unsupported period.

Review the explanation after the result

Ask whether the narrative matches the tested measure, units and limitations. Correct SQL for completed-order amount still does not establish recognized revenue, profit or a causal effect of a campaign.

Exercise: add another completed order with the same amount as an existing order. Predict why a SUM(DISTINCT amount) repair becomes more misleading, then verify the order-grain query against the source-row calculator.

NeuraPath's Data Analytics with Generative AI course connects AI-assisted SQL with independent verification. A useful explanation follows a tested query and a clear metric contract.

Continue learning

This article is part of the Generative AI for verified analyst work sequence. Use the neighbouring tasks when you need the prerequisite or the next application.

PK
Pankit Kumar
Lead Instructor, NeuraPath Academy

Pankit Kumar has 10 years in Data Science & AI, building and shipping production systems in regulated pharma and clinical environments. He is a freelance trainer at Boston Institute of Analytics, AnalytixLabs and Scaler, and has taught this material to thousands of working professionals.

This article is part of our Data Analytics with Generative AI programme — 3–4 months. The full analyst stack — Excel, SQL, Power BI and Python pipelines — then a generative-AI layer you can prove is right.

Explore Data Analytics with Generative AI
Counselling is free · no obligation

Not sure which programme fits?

Tell us your background and we will map it to the right entry point — including saying so when a cheaper programme is the better fit. A counsellor replies within one working day.