Interogări SQL pe două tabele — JOIN, subinterogări şi agregare
INNER JOIN, LEFT JOIN, subinterogări cu MAX/MIN/AVG, GROUP BY şi DISTINCT — tot ce cere Subiectul I când baza de date are două tabele legate. 40 de probleme rezolvate.
Există două feluri de subiecte de baze de date la atestat. În primul, baza de date se construieşte de la zero: creezi tabelul, introduci datele, afişezi ceva, modifici ceva — patru paşi pe un singur tabel. Acela e explicat la Baze de date şi SQL la atestatul de informatică.
În al doilea, baza de date există deja, are două tabele legate între ele, şi tot ce ţi se cere sunt două interogări. Enunţul e scurt — „afişaţi numele angajaţilor din departamentul Comercial" — şi exact de aceea e mai greu: nu-ţi mai spune nimeni ce structură să scrii.
Pagina asta acoperă al doilea fel, pe 40 de probleme rezolvate din sesiunea Galaţi 2026, grupate pe tehnica pe care o cer.
Tiparul care se repetă la toate cele 40
| Cerinţa | Ce atinge | Ce cere de fapt |
|---|---|---|
| a) | un singur tabel | SELECT cu ORDER BY, WHERE sau o funcţie de agregare |
| b) | ambele tabele | joncţiune, de obicei plus o filtrare sau o subinterogare |
Nu e o coincidenţă: cerinţa a) verifică dacă ştii să citeşti dintr-un tabel, cerinţa b) dacă ai înţeles de ce sunt două. Odată ce vezi tiparul, fiecare problemă se descompune în aceleaşi două întrebări: ce coloane se cer? şi din câte tabele vin?
Cele patru baze de date din sesiune, ca să ai contextul exemplelor de mai jos:
| Baza de date | Tabelele | Legătura |
|---|---|---|
| FIRMA | Angajati, Departamente |
idd |
| FOOD_DELIVERY | Restaurante, Comenzi |
idr |
| DIVERTISMENT | Filme, Cinematografe |
idc |
| GAMING | Jucatori, Jocuri |
idj |
De ce sunt două tabele şi nu unul
Un angajat lucrează într-un departament. Dacă denumirea departamentului ar fi scrisă în tabelul
Angajati, „Comercial" s-ar repeta la fiecare dintre cei 30 de oameni care lucrează acolo. La o
redenumire ar trebui modificate 30 de rânduri, iar o singură greşeală de tastare ar crea un
departament fantomă.
Soluţia e să scrii denumirea o singură dată, într-un tabel separat, iar în Angajati să păstrezi
doar un cod care trimite la ea:
Angajati Departamente
nume idd idd denumire data_infiintare
Popescu D01 ───────────────► D01 Comercial 2015-03-01
Ionescu D01 ───────────────┘
Georgescu D02 ───────────────► D02 Financiar 2012-09-15
Coloana idd din Angajati se numeşte cheie externă: nu conţine informaţie în sine, doar adresa
rândului din celălalt tabel. Asta rezolvă problema repetării, dar creează alta: numele angajatului şi
denumirea departamentului lui nu mai sunt în acelaşi loc. De aici încolo, orice întrebare care le
amestecă are nevoie de o joncţiune.
Tehnica 1 — joncţiunea (INNER JOIN)
Joncţiunea lipeşte două tabele pe coloana care le e comună:
SELECT a.nume, a.prenume, d.denumire AS departament
FROM Angajati a
INNER JOIN Departamente d ON a.idd = d.idd;
aşidsunt aliasuri — prescurtări pentru numele tabelelor. Devin obligatorii când o coloană există în ambele tabele (idd): fără prefix, serverul nu ştie la care te referi.ON a.idd = d.idde condiţia de legătură. Nu e opţională: fără ea obţii produsul cartezian — fiecare angajat combinat cu fiecare departament. Nu dă nicio eroare, doar de cinci ori mai multe rânduri, toate false.
Forma echivalentă, mai veche, acceptată la fel în Access şi Oracle:
SELECT a.nume, d.denumire
FROM Angajati a, Departamente d
WHERE a.idd = d.idd;
Un rând din tabelul „părinte" apare o dată pentru fiecare rând care trimite la el: un restaurant cu trei comenzi apare de trei ori în rezultat, cu altă comandă pe fiecare rând. Corect — sunt comenzi diferite. Devine problemă doar când se cere lista restaurantelor, nu a comenzilor; atunci vezi tehnica 6.
Probleme: angajaţii şi departamentul fiecăruia · filme şi cinematografe · jucători şi jocurile lor de pe PC · restaurante şi valorile comenzilor · angajaţii din primul departament înfiinţat
Tehnica 2 — LEFT JOIN, când nu vrei să pierzi rânduri
INNER JOIN păstrează doar rândurile care au corespondent în ambele tabele. Un departament fără
angajaţi, un jucător fără jocuri, un restaurant fără comenzi — toate dispar din rezultat. Nu apare
nicio eroare; răspunsul arată corect, doar că îi lipseşte un rând.
LEFT JOIN păstrează tot din tabelul scris primul şi completează cu NULL unde nu găseşte
potrivire:
SELECT d.denumire, COUNT(a.ida) AS nr_angajati
FROM Departamente d
LEFT JOIN Angajati a ON d.idd = a.idd
GROUP BY d.denumire;
Şi aici vine detaliul care decide dacă răspunsul e corect — COUNT(a.ida), nu COUNT(*):
| Scris | Pentru un departament fără angajaţi |
|---|---|
COUNT(*) |
1 — numără rândul plin de NULL produs de joncţiune |
COUNT(a.ida) |
0 — COUNT pe o coloană ignoră valorile NULL |
Un „1" în loc de „0". Trei variante de scriere (INNER JOIN, LEFT JOIN + COUNT(*),
LEFT JOIN + COUNT(coloana)), trei rezultate diferite, niciuna nu dă eroare.
O a doua capcană a lui LEFT JOIN: o condiţie pusă în WHERE pe tabelul din dreapta anulează tot
efectul, pentru că elimină rândurile cu NULL. Condiţiile pe tabelul din dreapta se mută în ON;
în WHERE rămân doar cele pe tabelul păstrat.
Probleme: număr de angajaţi pe fiecare departament · număr de jocuri pe fiecare jucător · filme pe fiecare cinematograf · comenzi pe fiecare tip de bucătărie · jucătorii din România şi jocurile lor
Tehnica 3 — funcţiile de agregare
Cinci funcţii, toate cu acelaşi comportament: strâng mai multe rânduri într-unul singur.
| Funcţie | Ce dă | Cuvântul din enunţ |
|---|---|---|
COUNT(*) |
câte rânduri | „numărul", „câţi/câte" |
SUM(x) |
suma valorilor | „suma totală", „fondul de salarii", „încasările" |
AVG(x) |
media | „media", „nivelul mediu", „preţul mediu" |
MIN(x) |
cea mai mică valoare | „minim", „cel mai ieftin", „primul" (la date) |
MAX(x) |
cea mai mare valoare | „maxim", „cel mai lung", „cel mai recent" (la date) |
Trei lucruri de ştiut despre toate cinci:
- Ignoră valorile
NULL.AVGîmparte la numărul de rânduri care au valoare, deci nu eSUM(x) / COUNT(*).SUMnu trateazăNULLca0— pur şi simplu nu-l adună. COUNT(*)şiCOUNT(coloana)sunt diferite. Al doilea nu numără rândurile în care coloana e necompletată. Pe un tabel plin arată identic; subiectele conţin aproape întotdeauna un câmp gol.- Rezultatul e un singur rând. Nu poţi pune o coloană obişnuită lângă o agregare fără
GROUP BY— vezi tehnica 4.
La AVG şi la orice împărţire, ROUND(..., 2) e reflexul corect: media a trei salarii dă
3866.6666..., iar o coloană de bani cu 13 zecimale arată ca o greşeală.
Probleme: numărul de angajaţi şi cei din Comercial · fondul de salarii · salariul mediu · suma comenzilor livrate · preţul minim al biletului · preţul mediu la Dramă · numărul de filme SF · numărul total de filme
Tehnica 4 — GROUP BY, când enunţul spune fiecare
Un singur cuvânt schimbă interogarea: „fiecare".
"numarul de angajati din firma" -> COUNT(*) un rand
"numarul de angajati din fiecare departament"-> COUNT(*) + GROUP BY un rand per departament
GROUP BY aşază rândurile în grămăjoare după valoarea unei coloane, iar funcţia de agregare se
calculează separat în fiecare grămăjoară.
Regula care nu se încalcă niciodată: tot ce apare în SELECT şi nu e într-o funcţie de agregare
trebuie să apară în GROUP BY. Altfel, în Oracle şi SQL Server primeşti eroare
(not a single-group group function), iar în MySQL şi SQLite — mai rău — interogarea merge şi
afişează o valoare aleasă arbitrar. Rezultat credibil, greşit.
Şi diferenţa dintre WHERE şi HAVING, care vine din ordinea de execuţie:
FROM + JOIN -> lipeste tabelele
WHERE -> arunca RANDURI care nu trec conditia
GROUP BY -> aseaza ce a ramas in grupuri
COUNT/SUM/... -> calculeaza in fiecare grup
HAVING -> arunca GRUPURI care nu trec conditia
ORDER BY -> sorteaza rezultatul final
Condiţie pe statusul unei comenzi (o proprietate a rândului) → WHERE. Condiţie pe suma încasată de
un restaurant (o proprietate a grupului) → HAVING SUM(c.valoare) > 200.
Probleme: angajaţi pe fiecare departament · suma comenzilor livrate pe restaurant · comenzi anulate pe restaurant · jocuri pe fiecare platformă · filme pe fiecare cinematograf
Tehnica 5 — subinterogarea: cine are maximul
Cea mai cerută construcţie din tot Subiectul I, şi cea care merită învăţată prima. Apare de fiecare dată când enunţul spune „cel cu valoarea maximă / minimă" sau „peste medie".
Problema: MAX(salariul) îţi spune cât e salariul maxim, dar strânge toate rândurile într-unul —
deci pierde numele. Ca să afişezi rândul, maximul trebuie calculat separat, într-o interogare
interioară:
SELECT nume, prenume, salariul
FROM Angajati
WHERE salariul = (SELECT MAX(salariul) FROM Angajati);
Se execută în doi paşi: subinterogarea dă 5200, apoi WHERE compară fiecare rând cu valoarea aceea.
Ce nu funcţionează, şi de ce:
| Scris | Ce se întâmplă |
|---|---|
SELECT nume, MAX(salariul) FROM Angajati |
eroare în Oracle; în MySQL/SQLite, maximul lângă un nume arbitrar |
WHERE salariul = MAX(salariul) |
eroare: agregările nu se pot folosi direct în WHERE |
ORDER BY salariul DESC + primul rând |
nu e o interogare, e o citire cu ochii; la egalitate pe maxim pierzi jumătate din răspuns |
WHERE salariul = 5200 |
ai citit răspunsul din date; se strică la primul angajat nou |
Egalitatea pe maxim nu e o ipoteză teoretică: la ratinguri (4.8), la durate în minute sau la date
calendaristice, două rânduri egale sunt regula. De altfel, enunţurile o recunosc explicit —
„comanda/comenzile", „jucătorului (sau jucătorilor)".
Aceeaşi construcţie acoperă, cu mici variaţii:
MINîn loc deMAX— „primul departament înfiinţat", „cel mai ieftin bilet"MAXpe o dată — „cinematograful deschis cel mai recent"MAX(LENGTH(denumire))— „jocul cu denumirea cea mai lungă"; maximul se calculează pe o valoare care nu e stocată nicăieri> (SELECT AVG(nivel) ...)— „jucătorii cu nivelul peste medie". Aici subinterogarea e obligatorie: media nu există ca valoare în tabel, iarWHEREse evaluează rând cu rând, deci nu poate cunoaşte o medie.
Probleme: angajaţii cu salariul maxim · comanda cu valoarea maximă · restaurantele cu rating maxim · filmele cu durata maximă · scorul maxim la jocuri · jucătorii peste nivelul mediu · jocul cu denumirea cea mai lungă · primul jucător înscris · departamentul înfiinţat cel mai recent
Tehnica 6 — DISTINCT, când lista are dubluri
După o joncţiune, numele restaurantului apare o dată pentru fiecare comandă a lui. Dacă se cere lista restaurantelor, dublurile trebuie eliminate:
SELECT DISTINCT r.nume
FROM Restaurante r
INNER JOIN Comenzi c ON r.idr = c.idr
WHERE c.metoda_plata = 'card';
Detaliul care încurcă pe toată lumea: DISTINCT se aplică pe tot rândul, nu pe o coloană. Deci
SELECT DISTINCT r.nume, c.idc FROM ... -- DUBLURILE RAMAN
pentru că perechea (nume, idc) e unică la fiecare comandă — nu există două rânduri identice de
eliminat. DISTINCT nu e o funcţie care se aplică pe r.nume; e o instrucţiune care spune „aruncă
rândurile repetate". Ca să funcţioneze, în SELECT trebuie să rămână doar coloanele după care
vrei unicitate.
Variantă care evită dublurile prin construcţie, fără joncţiune:
SELECT nume FROM Restaurante
WHERE idr IN (SELECT idr FROM Comenzi WHERE metoda_plata = 'card');
Iar când se cere câte valori distincte există, nu care sunt: COUNT(DISTINCT tip_bucatarie).
Diferenţa dintre COUNT(*) (6 restaurante) şi COUNT(DISTINCT tip_bucatarie) (5 tipuri) e un singur
rând dublat — şi toată diferenţa dintre corect şi greşit.
Probleme: restaurantele cu plăţi prin card, fără dubluri · restaurantele cu comenzi în luna curentă · tipuri de bucătărie distincte · genurile distincte de jocuri
Tehnica 7 — ORDER BY
ORDER BY salariul DESC, nume ASC
- se scrie ultimul în interogare, după
FROM,WHEREşiGROUP BY - crescător e implicit (
ASC);DESCse pune după coloana la care se referă, iar fiecare coloană îşi cere direcţia separat - se poate ordona şi după o coloană care nu e afişată — sortarea se face pe rânduri, nu pe ce se vede
Al doilea criteriu nu e decorativ: la salarii egale, fără el ordinea rămâne la voia serverului şi
poate diferi de la o rulare la alta. „Ordine alfabetică" la o listă de persoane înseamnă
ORDER BY nume, prenume, nu doar nume.
Un detaliu care surprinde: ORDER BY pe un câmp text care conţine numere sortează alfabetic —
'90' iese înaintea lui '100', pentru că se compară caracter cu caracter. Acelaşi lucru la date
stocate ca text: '09.12.2020' pare mai mare decât '11.01.2012'. E motivul pentru care tipul
coloanei (number, date) chiar contează.
Probleme: angajaţi în ordine alfabetică · salarii descrescător · jocurile după scor · filme după preţul biletului · restaurante alfabetic · jucătorii după username
Tehnica 8 — filtrarea: praguri, şabloane, text şi date
Pragurile se citesc din enunţ
| Formularea din enunţ | Operator |
|---|---|
| „mai mare de 4000" | > 4000 (strict) |
| „de cel puţin 4000", „minim 4000" | >= 4000 |
| „între 80 şi 100" | BETWEEN 80 AND 100 (inclusiv ambele capete) |
| „strict între 80 şi 100" | > 80 AND < 100 |
| „diferit de" | <> (sau !=) |
Subiectele conţin aproape întotdeauna o valoare aflată exact pe prag — un salariu de exact 4000,
un film de exact 150 de minute. Acolo se decide dacă foloseşti > sau >=, iar un semn greşit
schimbă rezultatul fără să dea nicio eroare.
BETWEEN are o capcană proprie: ordinea argumentelor. BETWEEN 100 AND 80 întoarce zero rânduri,
fără eroare — serverul verifică „≥ 100 şi ≤ 80", condiţie imposibilă.
LIKE — potrivire după şablon
| Şablon | Găseşte |
|---|---|
'A%' |
începe cu A |
'%A' |
se termină cu A |
'%A%' |
conţine A oriunde |
'A_ex%' |
A, exact un caracter oarecare, apoi „ex" |
În Access, caracterul pentru „orice şir" e *, nu %. Iar cu = în loc de LIKE, % e un
caracter obişnuit: WHERE username = 'A%' caută textul literal „A%".
Text: literă mare/mică şi diacritice
Două surse de „zero rânduri" fără niciun mesaj de eroare:
- Oracle e sensibil la literă mare/mică la compararea şirurilor:
'comercial'nu găseşte'Comercial'. Access şi SQL Server sunt, implicit, insensibile. Varianta care merge oriunde:WHERE UPPER(d.denumire) = 'COMERCIAL'. - Enunţul scrie cu diacritice, tabelul poate să nu aibă. „Galaţi", „Bucureşti", „România",
„Dramă" — dacă în tabel valoarea e
Galati, condiţia= 'Galaţi'nu potriveşte nimic. Condiţia se scrie ca valoarea din tabel, nu ca în enunţ; când nu poţi verifica,LIKE 'Gala%'.
Funcţii pe text: SUBSTR şi LENGTH
Apar la cerinţele care cer informaţie ascunsă într-un şir — tipic, CNP-ul:
SUBSTR(cnp, 1, 1) -- prima cifra: gen + secol
SUBSTR(cnp, 2, 2) -- anul nasterii, ultimele doua cifre
Al doilea argument e poziţia de start, al treilea câte caractere (nu poziţia de sfârşit). Caracterele se numără de la 1, nu de la 0 ca la vectori.
Prima cifră a CNP-ului: 1/2 = născut 1900–1999, 5/6 = după 2000, impar = masculin, par =
feminin. Deci anul nașterii nu se poate presupune ca '19' || SUBSTR(cnp, 2, 2) — pentru cineva
născut în 2001 ar da 1901. Un secol greşit, perfect plauzibil, invizibil.
| Funcţie | Oracle / SQLite / MySQL | Access / SQL Server |
|---|---|---|
| subşir | SUBSTR(s, 1, 1) |
Mid(s, 1, 1) / SUBSTRING(s, 1, 1) |
| lungime | LENGTH(s) |
LEN(s) |
| concatenare | s1 || s2 |
s1 & s2 / s1 + s2 |
Date: luna curentă nu e o lună anume
Nu se scrie WHERE data >= '2026-09-01' — ar fi corect o lună şi greşit tot restul anului. Data de
azi se citeşte de la sistem:
WHERE EXTRACT(MONTH FROM data_comanda) = EXTRACT(MONTH FROM CURRENT_DATE)
AND EXTRACT(YEAR FROM data_comanda) = EXTRACT(YEAR FROM CURRENT_DATE);
| Sistem | Data de azi | Luna dintr-o dată |
|---|---|---|
| SQL standard | CURRENT_DATE |
EXTRACT(MONTH FROM d) |
| Oracle | SYSDATE |
EXTRACT(MONTH FROM d), TO_CHAR(d, 'MM') |
| Access | Date() |
Month(d) |
| MySQL | CURDATE() |
MONTH(d) |
Condiţia pe an nu e opţională. Doar cu luna, o comandă din septembrie 2024 trece la fel de bine ca una din septembrie 2026 — iar rezultatul arată plauzibil, pentru că toate datele afişate sunt într-adevăr din septembrie.
Probleme: salarii peste 4000 · scoruri între 80 şi 100 · username care începe cu A · angajaţii de gen masculin, din CNP · anul naşterii din CNP · comenzile din luna curentă · restaurantele din Galaţi · filmele din Bucureşti
Tehnica 9 — UPDATE şi DELETE (rar, dar decisiv)
Doar patru din cele 40 de probleme cer modificarea datelor, şi toate patru se joacă pe aceeaşi distincţie:
UPDATE Angajati SET salariul = salariul + 100; -- fara WHERE: CERUT de enunt
UPDATE Comenzi SET valoare = valoare * 1.1 WHERE metoda_plata = 'cash'; -- cu WHERE: obligatoriu
Când enunţul spune „fiecărui angajat" sau „pentru toate filmele", lipsa lui WHERE e
răspunsul corect — merită un comentariu, ca să se vadă că nu ai uitat-o. Când spune „comenzile plătite
cash", WHERE e singurul lucru care stă între tine şi distrugerea întregului tabel.
SET salariul = salariul + 100 nu e o ecuaţie, e o atribuire: citeşte valoarea actuală a rândului,
adună, scrie rezultatul la loc. Iar SET salariul = 100 înlocuieşte — cea mai scumpă greşeală
posibilă.
La procente, singura confuzie care contează:
| Cerinţa | Scris corect | Greşeala tipică |
|---|---|---|
| „majoraţi cu 10%" | valoare * 1.1 |
valoare * 10 / 100 — dă 10% din valoare, adică o scade cu 90% |
| „măriţi cu 100" | salariul + 100 |
salariul * 100 |
Iar la DELETE, capcana e de altă natură: o cerinţă care şterge rânduri şi o alta care le numără
se contrazic. Dacă ştergi întâi, nu mai ai ce număra. Se execută numărarea prima, cu o explicaţie
scrisă — subiectul oficial e cel inconsecvent, nu tu.
Probleme: mărirea salariilor cu 100 · majorarea cu 10% a comenzilor cash · mărirea preţului biletelor · ştergerea comenzilor anulate
Greşelile care se repetă la toate cele 40
Cele adunate din toate rezolvările, în ordinea gravităţii. Toate au aceeaşi trăsătură: nu dau eroare.
- Joncţiune fără condiţia de legătură — produs cartezian. De cinci-zece ori mai multe rânduri, toate false.
SELECT coloana, MAX(x)fărăGROUP BY— eroare în Oracle, dar în MySQL/SQLite afişează maximul lângă o valoare arbitrară. Cea mai periculoasă, pentru că rezultatul arată perfect.UPDATE/DELETEfărăWHERE, când enunţul cerea o condiţie — datele sunt pierdute definitiv.COUNT(*)în loc deCOUNT(coloana)dupăLEFT JOIN—1în loc de0pentru grupurile goale.INNER JOINunde trebuiaLEFT JOIN— răspunsul e corect, doar incomplet. Se vede doar dacă numeri rândurile.- Condiţia pe an uitată la „luna curentă" — intră aceeaşi lună din toţi anii.
- Diacritice sau literă mică în şirul comparat — zero rânduri, fără mesaj.
>=în loc de>la un prag — exact valoarea de pe limită intră sau nu, iar subiectul o conţine dinadins.ORDER BY+ „iau primul rând" în loc de subinterogare cuMAX/MIN— pierzi rândurile egale.DISTINCTcu mai multe coloane înSELECT— nu elimină nimic, pentru că lucrează pe rândul întreg.WHEREîn loc deHAVINGpentru o condiţie pe o agregare — eroare.- Valoarea maximului sau media scrise de mână, citite din rezultatul cerinţei precedente — corect azi, greşit mâine.
Cum se exersează
Toate cele 40 de interogări de mai jos au fost rulate pe date de probă, în sqlite3, nu doar
scrise pe hârtie. Poţi face exact acelaşi lucru gratuit: instalează sqlite3 (sau foloseşte un
executor SQL în browser), creează cele două tabele cu CREATE TABLE, introdu cinci-zece rânduri
inventate şi rulează interogarea.
Verificarea care prinde cele mai multe greşeli e numărarea rândurilor: dacă ai 10 angajaţi şi interogarea întoarce 50 de rânduri, ai uitat condiţia de joncţiune. Dacă întoarce 0, e aproape sigur un şir scris altfel decât în tabel.
Pentru subiectele care construiesc baza de date de la zero — CREATE TABLE, INSERT, tipurile de
date din notaţia (N,5) / (T,20) — vezi
Baze de date şi SQL la atestatul de informatică.
Toate problemele din această categorie
- Baze de date DIVERTISMENT — filmele cu biletul peste 40 și cinematograful fiecăruiaBaze de date
- Baze de date DIVERTISMENT — filmele după prețul biletului și încasările de la CineGoldBaze de date
- Baze de date DIVERTISMENT — filmele mai lungi de 150 de minute și prețul mediu la DramăBaze de date
- Baze de date DIVERTISMENT — filmele în ordine alfabetică și cele de la Cinema CityBaze de date
- Baze de date DIVERTISMENT — lista cinematografelor și filmele cu durata maximăBaze de date
- Baze de date DIVERTISMENT — mărirea prețului biletelor și cinematograful cel mai nouBaze de date
- Baze de date DIVERTISMENT — numărul de filme pe cinematograf și prețurile de la Happy CinemaBaze de date
- Baze de date DIVERTISMENT — numărul total de filme și cinematografele din Cluj-NapocaBaze de date
- Baze de date DIVERTISMENT — prețul minim al biletului și filmele din BucureștiBaze de date
- Baze de date DIVERTISMENT — titluri în ordine alfabetică și numărul filmelor SFBaze de date
- Baze de date FIRMA — angajați în ordine alfabetică și numărul celor din FinanciarBaze de date
- Baze de date FIRMA — angajații cu salariul peste 4000 și departamentul fiecăruiaBaze de date
- Baze de date FIRMA — angajații de gen masculin (din CNP) și fondul de salariiBaze de date
- Baze de date FIRMA — angajații și primul departament înființatBaze de date
- Baze de date FIRMA — lista departamentelor și angajații cu salariul maximBaze de date
- Baze de date FIRMA — mărirea salariilor și departamentul cel mai nouBaze de date
- Baze de date FIRMA — numărul de angajați pe fiecare departament și telefoanele din FinanciarBaze de date
- Baze de date FIRMA — numărul de angajați și angajații din departamentul ComercialBaze de date
- Baze de date FIRMA — salarii în ordine descrescătoare și salariul mediuBaze de date
- Baze de date FIRMA — salariul minim și anul nașterii din CNPBaze de date
- Baze de date FOOD_DELIVERY — comanda cu valoarea maximă și restaurantul eiBaze de date
- Baze de date FOOD_DELIVERY — comenzile din luna curentăBaze de date
- Baze de date FOOD_DELIVERY — comenzile plătite cu cardul și restaurantele lor, fără dubluriBaze de date
- Baze de date FOOD_DELIVERY — majorarea cu 10% a comenzilor plătite cashBaze de date
- Baze de date FOOD_DELIVERY — restaurante ordonate alfabetic și valorile comenzilorBaze de date
- Baze de date FOOD_DELIVERY — restaurantele cu rating maxim și comenzile lorBaze de date
- Baze de date FOOD_DELIVERY — restaurantele din Galați și comenzile lorBaze de date
- Baze de date FOOD_DELIVERY — suma comenzilor livrate, în total și pe restaurantBaze de date
- Baze de date FOOD_DELIVERY — tipuri de bucătărie distincte și numărul de comenzi pe tipBaze de date
- Baze de date FOOD_DELIVERY — ștergerea comenzilor anulate și numărul lor pe restaurantBaze de date
- Baze de date GAMING — genurile distincte de jocuri și numărul de jocuri pe jucătorBaze de date
- Baze de date GAMING — jocul cu denumirea cea mai lungăBaze de date
- Baze de date GAMING — jocuri pe fiecare platformă și scoruri între 80 și 100Baze de date
- Baze de date GAMING — jocurile ordonate descrescător după scorBaze de date
- Baze de date GAMING — jucătorii cu username care începe cu litera ABaze de date
- Baze de date GAMING — jucătorii din România și jocurile lorBaze de date
- Baze de date GAMING — jucătorii în ordine alfabetică și jocurile de pe PCBaze de date
- Baze de date GAMING — nivelul mediu și jucătorii peste medieBaze de date
- Baze de date GAMING — primul jucător înscris și jocurile luiBaze de date
- Baze de date GAMING — scorul maxim și jocurile la care s-a obținutBaze de date