TestGorilla SQL Assessment: Identify Your Test Type and Practice the Right Skills
Quick Overview
Choose preparation from the invitation’s named SQL test, then reconcile an original repair-shop dataset without join inflation, lost zero rows, or incorrect DISTINCT totals.
The name “TestGorilla SQL assessment” does not identify one universal test. A Microsoft SQL Server knowledge test, a SQLite coding task, and an employer's custom SQL exercise are not interchangeable. A short invitation check helps you spend practice time on the tools and execution rules you will actually use.
Identify the test, then practice producing a result you can verify. This guide gives you an invitation checklist, original SQL Server reasoning prompts, and a runnable SQLite exercise with exact expected rows. For a targeted warm-up, use Write left-join queries with tricky filters and predict which unmatched rows survive before running the query.
Evidence boundary: Official TestGorilla pages support the named product distinctions below. One public 2026 candidate discussion supplies limited anecdotal context, not a universal assessment format. The dataset, queries, failure cases, and preparation recommendations are original PracHub teaching material, not TestGorilla questions or answer keys.

Identify your SQL test before choosing practice
Official facts checked October 11, 2026: TestGorilla's Microsoft SQL Server test page currently labels that product Intermediate and 10 minutes. Its published coverage includes tools and environment setup, database design and development, performance tuning, and administration and security. That timer belongs to the named test; it does not establish the duration of a whole employer assessment.
The separate SQLite coding entry-level test describes a query-writing database exercise. TestGorilla's custom coding test documentation currently lists SQL with SQLite. Check the module and runtime before choosing a practice environment; these sources do not establish that every invitation uses SQLite.
| What the invitation names | Prepare this first | What you still need to verify |
|---|---|---|
| Microsoft SQL Server | SQL Server tools, design, tuning, and administration concepts | Question format, selected test, and total assessment duration |
| SQLite coding | Read a schema, write a query, check exact output | Runtime version, available functions, required columns and ordering |
| Custom SQL test | Follow the employer's task contract | Dialect, starter database, allowed statements, and submission action |
| Only “SQL assessment” | Gather the missing details | Test name and execution environment remain unknown |
Editorial inference: The same word “SQL” can describe knowledge recognition, executable query work, or a broader database discussion. Check what you will actually do before allocating preparation time. If the invitation is vague, ask the hiring contact for the test name and dialect; do not request private questions.
Which candidate reports are useful?
Candidate report: A March 2026 public Data Engineer assessment discussion includes a respondent describing an MS SQL Server test and short per-test timing. This is one person's account of their assessment. It does not identify every employer configuration or prove that your invitation contains the same modules.
Our research did not establish two independent, same-cycle reports for one exact SQL assessment configuration. We therefore do not reconstruct a universal sequence, question count, passing mark, or hidden grading rule. Use public accounts to notice preparation risks, then resolve those risks against your invitation and official instructions.
A practical note can contain five fields: named module, dialect, task format, visible timer, and allowed tools. If no dialect is named, record “dialect not specified” instead of choosing one silently. Do not fill a blank with a Reddit comment from another role, or treat the entire assessment's duration as the SQL section's timer.
Practice SQL Server reasoning separately from query writing
The following prompts are original practice, organized around the published SQL Server coverage. They are not predictions of the test's question wording. Answer with an observation, a plausible explanation, and the next check that would distinguish it from alternatives.
Tools and environment: Your application connects successfully, but a query run in a management tool fails. Before changing permissions, compare the server or instance, database, authentication identity, and connection context. A connection is evidence that some authentication succeeded; it is not proof that the same identity has access to every database object.
Design and development: A repair has several charges and several inspection runs. Which key identifies one repair, and which keys identify child records? Explain why joining both child tables directly changes the number of contributing rows. A foreign key relationship alone does not make a one-to-many join one-to-one.
Performance: A report becomes slow for a large shop but remains fast for a small one. Request the query, parameter values, data distribution, and execution-plan evidence before recommending an index. Microsoft's index architecture and design guide discusses choosing indexes for workload needs and their maintenance costs. “Index every column” is not a defensible diagnosis.
Administration and security: A reporting identity needs to read approved reporting data but should not modify source records. Describe the required operations and the scope of access you would verify. Do not solve a permissions question by granting broad administrative rights. In practice, use your organization's approved access procedure and test with the intended identity.
These answers require SQL Server-specific follow-up in a real SQL Server environment. The SQLite exercise below verifies relational query behavior; it does not validate SQL Server permissions, administration, tooling, or execution plans.
Original SQLite task: reconcile a repair-shop report
Return one row per shop, including shops with no closed repairs. For each shop, report the count of closed repairs, the sum of approved charges on those repairs, and the number of passed inspection runs on those repairs. Count every passed run, not merely repairs that ever passed. Sort by shop_id ascending. Amounts are integer cents, and missing child totals should display zero.
Every primary key is unique. Each repair belongs to one existing shop; each charge and run belongs to one repair. Repeated amounts are separate legitimate charges. The small fixture uses only closed and open repairs, approved and rejected charges, and integer passed values of zero or one.
CREATE TABLE shops (
shop_id INTEGER PRIMARY KEY, shop_name TEXT NOT NULL
);
CREATE TABLE repairs (
repair_id INTEGER PRIMARY KEY, shop_id INTEGER NOT NULL,
state TEXT NOT NULL
);
CREATE TABLE charges (
charge_id INTEGER PRIMARY KEY, repair_id INTEGER NOT NULL,
amount_cents INTEGER NOT NULL, status TEXT NOT NULL
);
CREATE TABLE runs (
run_id INTEGER PRIMARY KEY, repair_id INTEGER NOT NULL,
passed INTEGER NOT NULL
);
INSERT INTO shops VALUES (1,'North'),(2,'South'),(3,'West');
INSERT INTO repairs VALUES
(101,1,'closed'),(102,1,'closed'),
(103,2,'open'),(104,2,'closed');
INSERT INTO charges VALUES
(1,101,1200,'approved'),(2,101,300,'approved'),
(3,102,700,'rejected'),(4,104,900,'approved'),
(5,104,900,'approved'),(6,103,500,'approved');
INSERT INTO runs VALUES
(1,101,0),(2,101,1),(3,101,1),
(4,102,1),(5,104,0),(6,104,0);
Before coding, write the expected result. North has two closed repairs. Repair 101 contributes 1,500 cents and two passing runs; repair 102 contributes no approved charge and one passing run. South's open repair 103 contributes nothing, while closed repair 104 contributes two separate 900-cent charges. West must remain visible.
| shop_id | shop_name | closed_repairs | approved_cents | passed_runs |
|---|---|---|---|---|
| 1 | North | 2 | 1500 | 3 |
| 2 | South | 1 | 1800 | 0 |
| 3 | West | 0 | 0 | 0 |
Build the query at the correct grain
Summarize each child table to one row per repair before joining it to the repair list. The final grouping then combines repair-level measures into one shop row. Put the closed-repair condition in the outer join so a shop without a qualifying repair still survives.
WITH approved AS (
SELECT repair_id, SUM(amount_cents) AS approved_cents
FROM charges
WHERE status = 'approved'
GROUP BY repair_id
), passed AS (
SELECT repair_id, COUNT(*) AS passed_runs
FROM runs
WHERE passed = 1
GROUP BY repair_id
)
SELECT s.shop_id, s.shop_name,
COUNT(r.repair_id) AS closed_repairs,
COALESCE(SUM(a.approved_cents), 0) AS approved_cents,
COALESCE(SUM(p.passed_runs), 0) AS passed_runs
FROM shops AS s
LEFT JOIN repairs AS r
ON r.shop_id = s.shop_id AND r.state = 'closed'
LEFT JOIN approved AS a ON a.repair_id = r.repair_id
LEFT JOIN passed AS p ON p.repair_id = r.repair_id
GROUP BY s.shop_id, s.shop_name
ORDER BY s.shop_id;
The proof starts with cardinality: each child summary has at most one row for a repair ID. Joining either summary therefore cannot multiply a repair. Counting the non-null repair key counts closed repairs, while summing the summaries accumulates each repair's measure once.
SQLite's SELECT documentation explains outer-join null extension and filter processing. Its aggregate documentation distinguishes counting all rows from counting non-null expressions and documents SUM on empty inputs. Here, COUNT(r.repair_id) avoids counting West's null-extended placeholder as a repair, and COALESCE makes missing monetary and run totals explicit zeros.

Diagnose three plausible wrong answers
Joining raw children: Repair 101 has two approved charges and three total runs. Joining both raw tables produces six rows for that repair before grouping. Its approved amount becomes 4,500 cents if every charge is repeated for all three runs. Applying a passing-run filter changes the multiplier but does not restore the original grain.
Using SUM(DISTINCT amount_cents): The two approved 900-cent charges for repair 104 are different records. Distinct amounts collapse them into 900, even though the correct total is 1,800. Deduplication must follow record identity and the business contract, not coincidentally equal measures.
Moving r.state = 'closed' into WHERE: West's null-extended repair row fails that condition, so the shop disappears. A filter on optional right-side data can change an outer join's meaning. Explain the desired population before moving predicates for readability or performance.
When a total is wrong, inspect one repair before inspecting the final shop aggregate. List its charge IDs and run IDs, count the rows produced by each join, then reconcile the independent child summaries. This makes a row multiplier visible. A final total alone cannot tell you whether the error came from eligibility, duplicate contribution, or a missing shop. Keep that short reconciliation beside the query when explaining a fix; it lets another reader reproduce the diagnosis without trusting your description.
The query also separates passed runs from passed repairs. If the requirement changes to “number of repairs with at least one pass,” use a repair-level indicator instead of summing run counts. North would then have two passed repairs, not three passed runs. That distinction belongs in the contract, not in a last-minute formatting fix.
Verify output changes, not only the original sample
Add one approved charge to an open repair: the report must stay unchanged. Add a rejected charge to a closed repair: it must stay unchanged again. Add a new shop with no repairs: a zero row must appear. Add a passing run to repair 101: North's passed-run count rises by one, while its charge total and repair count remain fixed.
Then add another approved 900-cent charge to repair 104. South should increase by 900; a DISTINCT workaround will fail this check. Change repair 103 from open to closed: South's repair count rises to two, and its existing 500-cent charge starts contributing. These controlled changes identify which rule a query actually implements.
Use a fresh database or rollback between cases so one change does not contaminate the next. Compare column names, row order, counts, and integer totals. The local fixture checks the displayed query and controlled data changes. It does not reveal hidden assessment cases or measure production performance.
Five PracHub questions for focused SQL practice
These are verified, candidate-reported PracHub practice records. They develop transferable skills; they are not claims that TestGorilla uses those questions. Some pages may require an account or Premium access. Keep the task's own dialect separate from the concept being practiced.
| Complete PracHub question | What to verify |
|---|---|
| Write left-join queries with tricky filters | Preserve the intended population when filtering child rows |
| Write conditional aggregation SQL queries | Match each conditional measure to its contributing rows |
| Reason About Composite Join Keys and Predicate Placement | Check the complete key and the location of optional-side conditions |
| Optimize a SQL query plan tree | Explain row flow before proposing a tuning change |
| Explain Database Index Benefits and Write Costs | Balance lookup benefits against maintenance costs |
Finish the task your invitation actually requests
Before a coding test, identify the required output shape and available execution controls. Use visible practice or environment guidance to understand the editor, then follow the assessment's actual instructions for running and submitting. A locally successful query and a submitted assessment are different observable states. Confirm the platform's completion message rather than assuming a run button also submits.
For a knowledge test, rehearse explaining the four SQL Server coverage areas without treating the SQLite fixture as a substitute. For a custom task, prioritize the supplied schema and rules. If the interface or invitation leaves a material detail unclear, seek clarification before starting a timed section where possible.
Continue with Write conditional aggregation SQL queries, then return to the repair fixture and change one requirement. For broader platform preparation, see TestGorilla Coding Test Guide: Practice Questions, Results, and Retakes. Use both guides to identify preparation gaps; neither establishes a passing threshold or predicts an interview outcome.
Sources and Further Reading
- TestGorilla: Microsoft SQL Server test
- TestGorilla: SQLite coding entry-level database operations
- TestGorilla: creating a custom coding test
- Candidate report: March 2026 Data Engineer assessment discussion
- SQLite: SELECT processing
- SQLite: built-in aggregate functions
- Microsoft: SQL Server index architecture and design guide
Comments (0)