Tutorial

Tehnici SQL avansate pentru testeri: JOIN-uri, subquery-uri și depistarea anomaliilor în date

Academia Testarii 12 iunie 2026
Înapoi la Blog

JOIN-urile și subquery-urile nu sunt doar treaba dezvoltatorilor — un tester care știe să interogheze baza de date direct găsește bug-uri pe care niciun test de interfață nu le vede. Iată cum.

Există un tip de bug care trece prin toate nivelurile de testare fără să fie prins: datele corupte silențios. Interfața arată verde, API‑ul răspunde 200 OK, rapoartele din JIRA sunt curate — dar în baza de date, o comandă are customer_id nul, un produs are stoc negativ sau o tranzacție bancară apare duplicată. Dacă nu știi SQL, nu ai cum să ajungi acolo.

Vestea bună: nu trebuie să fii DBA ca să scrii interogări puternice în MySQL, PostgreSQL sau SQL Server. Ai nevoie de câteva tehnici concrete, practicate până devin reflex. Hai să le trecem împreună.

TL;DR rapid

JOIN‑urile îți permit să corelezi tabele și să găsești înregistrări orfane sau inconsistente. Subquery‑urile îți dau flexibilitate să filtrezi seturi de date complexe într‑o singură interogare. Funcțiile de agregare și window functions îți arată anomaliile statistice. Combinate, aceste tehnici transformă baza de date dintr‑o cutie neagră într‑un instrument de investigație.

JOIN‑uri — nu doar INNER, ci și cele care scot la iveală problemele

Majoritatea testerilor știu de INNER JOIN. Problema e că INNER JOIN ascunde tocmai datele lipsă — returnează doar înregistrările care au corespondent în ambele tabele.

Când vrei să depistezi anomalii, LEFT JOIN este prietenul tău cel mai bun. Un exemplu clasic într‑un sistem de e‑commerce:

SELECT o.order_id, o.customer_id, c.name

FROM orders o

LEFT JOIN customers c ON o.customer_id = c.id

WHERE c.id IS NULL;

Această interogare îți returnează toate comenzile care nu au un client asociat în tabela customers — adică date orfane, un bug clasic de integritate referențială. Dacă găsești zece rânduri aici, ai un defect real pe care niciun test de UI nu l‑ar fi prins.

Mai există FULL OUTER JOIN, util când vrei să compari două seturi de date și să găsești tot ce nu se potrivește — de exemplu, reconcilierea unui fișier de import cu ce a ajuns efectiv în baza de date. Dacă lucrezi pe MySQL, FULL OUTER JOIN se simulează cu UNION între LEFT și RIGHT JOIN — un detaliu tehnic de reținut când scrii test case‑uri de validare a migrărilor.

Subquery‑uri — interogări în interiorul interogărilor

Un subquery îți permite să folosești rezultatul unei interogări ca filtru pentru alta. Sună abstract, dar în practică e extrem de util pentru scenarii de genul: "arată-mi toți userii care au plasat cel puțin o comandă în ultima săptămână, dar nu au primit e‑mail de confirmare."

SELECT u.email

FROM users u

WHERE u.id IN (

 SELECT o.user_id

 FROM orders o

 WHERE o.created_at >= NOW() - INTERVAL 7 DAY

)

AND u.id NOT IN (

 SELECT recipient_id

 FROM email_log

 WHERE email_type = 'order_confirmation'

 AND sent_at >= NOW() - INTERVAL 7 DAY

);

Dacă această interogare returnează rânduri, ai un bug în fluxul de notificări. Asta e testare de date reală, nu mocking, nu stub — date de producție (sau de staging) care vorbesc direct.

Subquery‑urile corelate, cele care referențiază tabela exterioară, sunt mai puternice și mai costisitoare ca performanță — folosește‑le cu atenție pe seturi mari de date și verifică întotdeauna EXPLAIN înainte să rulezi pe o bază de producție.

Funcții de agregare și detectarea outlierilor statistici

COUNT, SUM, AVG, MIN, MAX — le știi. Dar combinate cu GROUP BY și HAVING, devin instrumente de detectare a anomaliilor.

Exemplu concret dintr‑un domeniu bancar: vrei să verifici dacă există conturi cu un număr neobișnuit de mare de tranzacții într‑o singură zi — un indicator de fraudă sau de bug în procesarea automată a plăților.

SELECT account_id, COUNT(*) AS nr_tranzactii, DATE(created_at) AS zi

FROM transactions

GROUP BY account_id, DATE(created_at)

HAVING COUNT(*) > 50

ORDER BY nr_tranzactii DESC;

Dacă un cont normal face 3‑5 tranzacții pe zi și tu găsești unul cu 300, ai fie un bug de procesare în batch, fie un caz care merită escalat imediat.

Window functions — disponibile în MySQL 8+, PostgreSQL, SQL Server — duc analiza și mai departe. ROW_NUMBER(), RANK(), LAG() și LEAD() îți permit să compari fiecare rând cu vecinul lui cronologic, fără să pierzi contextul individual al înregistrării. Util pentru testarea fluxurilor de stări (status workflow): o comandă care trece din "pending" direct în "delivered", sărind "shipped", e un bug de logică de business pe care îl prinzi cu LAG().

Tehnici practice de depistare a anomaliilor în date

Dincolo de JOIN‑uri și subquery‑uri, există un set de verificări pe care orice tester cu acces la baza de date ar trebui să le facă sistematic:

- Valori nule acolo unde nu ar trebui: SELECT COUNT(*) FROM orders WHERE payment_id IS NULL AND status = 'paid'; — o comandă plătită fără ID de plată e un bug garantat.

- Duplicate neașteptate: folosește COUNT(*) combinat cu HAVING COUNT(*) > 1 pe câmpurile care ar trebui să fie unice, dar nu au constraint UNIQUE aplicat.

- Valori în afara domeniului acceptabil: prețuri negative, cantități zero pe produse active, date de expirare în trecut pe carduri marcate ca valide.

- Inconsistențe între tabele denormalizate: dacă suma coloanei totals din orders_summary nu coincide cu SUM(amount) din orders_items, ai o problemă de sincronizare.

Un framework simplu: definește înainte de testare ce înseamnă "date valide" pentru fiecare entitate, scrie interogările care verifică exact aceste condiții și rulează-le ca parte din regression testing după fiecare deploy. Nu e automation în sensul Selenium sau Playwright, dar e tot o formă de testare automată — și una extrem de eficientă.

SQL în contextul unui workflow modern de QA

La DevTalks și la A4Q Summit, subiectul data quality revine constant în discuțiile despre ce înseamnă un tester complet în 2025. Nu mai e suficient să validezi comportamentul vizibil al aplicației. Backend‑ul, pipeline‑urile de date, integrările între microservicii — toate lasă urme în baza de date, iar testerul care știe să citească acele urme adaugă o valoare reală, măsurabilă.

Instrumentele ajută: Chrome DevTools îți arată request‑urile de rețea, Postman îți validează răspunsurile API, dar niciunul nu îți spune ce s‑a întâmplat efectiv în tabela transactions după ce ai apăsat "Plătește". Acolo intri tu, cu o interogare bine scrisă.

Un detaliu practic: dacă echipa ta folosește JIRA pentru bug tracking, obișnuiește‑te să atașezi la fiecare bug de tip "date incorecte" și interogarea SQL care l‑a demonstrat. E cel mai convingător attachment pe care îl poți pune lângă un screenshot.

Pune SQL‑ul în practică cu Academia Testarii

Dacă ai ajuns până aici și simți că vrei să treci de la teorie la exerciții reale — pe baze de date cu structuri similare celor din domeniile bancar, retail sau automotive — Academia Testarii are exact cursul de care ai nevoie.

Învățăm SQL pentru testeri pas cu pas: de la SELECT și filtrare, până la JOIN‑uri complexe, subquery‑uri corelate și window functions aplicate în scenarii reale de QA. Fără jargon inutil, cu exerciții hands‑on și feedback pe interogările tale.

Intră pe academiatestarii.ro, explorează programele disponibile și fă primul pas spre un profil de tester complet — unul care nu se oprește la interfață, ci merge direct la sursă. 🎯

#DeAziEstiTester #AcademiaTestarii #SoftwareTesting #TestareSoftware #QualityAssurance

Toate articoleleAutor: Academia Testarii