الرئيسية › الدروس › SQL: الربط، التجميع والاستعلامات الفرعية
SQL: الربط بين الجداول وGROUP BY وHAVING والاستعلامات الفرعية
اربط برشا tables في requête وحدة، احسب وجمّع حسب المجموعات بـ GROUP BY و HAVING، استعمل requête داخل أخرى، واحسب بالتواريخ.
دروس هذا الفصل
- الربط بين الـ tables (jointures)
- نحسبو ونجمّعو
- الاستعلامات الفرعية والتواريخ
الدرس 29.1 : الربط بين الـ tables (jointures)
الـ jointure تجمع الأسطر متاع زوز tables اللي يمشيو مع بعضهم: كل تلميذ مع القسم متاعو. تتكتب بـ JOIN والشرط اللي يربطهم بعد ON: الـ clé étrangère تساوي الـ clé primaire.
SELECT eleve.nom, classe.niveau, classe.salle
FROM eleve JOIN classe ON eleve.code_classe = classe.code;
INNER JOINوJOINنفس الشي: كان الأسطر اللي عندها شريك يبقاو.- الـ alias يقصّرو الأسامي:
FROM eleve e JOIN classe c ON e.code_classe = c.code. - نسلسلو برشا
JOINباش نعدّيو على ثلاثة tables، ونخلّيوWHEREباش نصفّيو.
انتبه : كي يكون عند زوز tables عمود بنفس الاسم، MySQL ما يعرفش أشكون ياخو: غلطة #1052 (« ambiguous »). اكتب table.colonne ولا alias.colonne.
بـ SQL
خدّم، وبعد زيد WHERE c.niveau = 'Bac SI' قبل الـ ORDER BY باش تخلّي كان تلامذة الباك.
CREATE TABLE classe (code VARCHAR(5) PRIMARY KEY, niveau VARCHAR(20) NOT NULL, salle VARCHAR(5));
CREATE TABLE eleve (
id INT PRIMARY KEY,
nom VARCHAR(30) NOT NULL,
code_classe VARCHAR(5),
moyenne DECIMAL(4,2),
date_naissance DATE,
FOREIGN KEY (code_classe) REFERENCES classe(code)
);
INSERT INTO classe VALUES ('4SI1', 'Bac SI', 'B12'), ('4SI2', 'Bac SI', 'B14'), ('3SI1', '3ème SI', 'A03');
INSERT INTO eleve VALUES
(1, 'Ben Salah', '4SI1', 12.50, '2008-03-14'),
(2, 'Trabelsi', '4SI1', 16.25, '2008-07-02'),
(3, 'Jaziri', '4SI2', 9.75, '2008-11-23'),
(4, 'Mansour', '4SI2', 14.00, '2007-12-30'),
(5, 'Bouzid', '3SI1', 11.00, '2009-05-05');
SELECT e.nom, c.niveau, c.salle
FROM eleve e JOIN classe c ON e.code_classe = c.code
ORDER BY e.nom;
الدرس 29.2 : نحسبو ونجمّعو
الـ fonctions d'agrégation
COUNT(*): عدد الأسطر.COUNT(colonne)ما يحسبش الـNULL.SUM(x): المجموع،AVG(x): المعدّل،MIN(x)وMAX(x): أصغر وأكبر قيمة.
SELECT COUNT(*) AS nb, AVG(moyenne) AS moy_generale, MAX(moyenne) AS meilleure FROM eleve;
GROUP BY و HAVING
GROUP BY يقسم الأسطر لـ مجموعات عندها نفس القيمة، والـ fonctions d'agrégation يحسبو نتيجة لكل مجموعة. HAVING بعد يصفّي المجموعات، كيما WHERE يصفّي الأسطر.
SELECT code_classe, COUNT(*) AS nb, AVG(moyenne) AS moy
FROM eleve
GROUP BY code_classe
HAVING COUNT(*) >= 2;
انتبه : العمود في الـ SELECT اللي موش fonction d'agrégation لازمو يكون في الـ GROUP BY. والشرط على COUNT ولا SUM يمشي في HAVING، عمرو ما يمشي في WHERE (غلطة #1111).
نصيحة : ترتيب الكتيبة ديما: SELECT … FROM … JOIN … WHERE … GROUP BY … HAVING … ORDER BY … LIMIT ….
بـ SQL
خدّم، وبعد بدّل HAVING COUNT(*) >= 2 بـ HAVING AVG(moyenne) >= 12: أنهوما الأقسام اللي يبقاو؟
CREATE TABLE classe (code VARCHAR(5) PRIMARY KEY, niveau VARCHAR(20) NOT NULL, salle VARCHAR(5));
CREATE TABLE eleve (
id INT PRIMARY KEY,
nom VARCHAR(30) NOT NULL,
code_classe VARCHAR(5),
moyenne DECIMAL(4,2),
date_naissance DATE,
FOREIGN KEY (code_classe) REFERENCES classe(code)
);
INSERT INTO classe VALUES ('4SI1', 'Bac SI', 'B12'), ('4SI2', 'Bac SI', 'B14'), ('3SI1', '3ème SI', 'A03');
INSERT INTO eleve VALUES
(1, 'Ben Salah', '4SI1', 12.50, '2008-03-14'),
(2, 'Trabelsi', '4SI1', 16.25, '2008-07-02'),
(3, 'Jaziri', '4SI2', 9.75, '2008-11-23'),
(4, 'Mansour', '4SI2', 14.00, '2007-12-30'),
(5, 'Bouzid', '3SI1', 11.00, '2009-05-05');
SELECT code_classe, COUNT(*) AS nb, AVG(moyenne) AS moy
FROM eleve
GROUP BY code_classe
HAVING COUNT(*) >= 2;
الدرس 29.3 : الاستعلامات الفرعية والتواريخ
requête داخل requête
الـ sous-requête هي SELECT بين أقواس، محطوطة في الـ WHERE متاع requête أخرى. تتحسب الأوّل، ومن بعد النتيجة متاعها تخدم في الشرط.
SELECT nom, moyenne FROM eleve
WHERE moyenne > (SELECT AVG(moyenne) FROM eleve);
SELECT nom FROM eleve
WHERE code_classe IN (SELECT code FROM classe WHERE niveau = 'Bac SI');
- مع
=،>،<…، الـ sous-requête لازمها تعطي قيمة وحدة. - مع
INوNOT IN، تعطي قائمة قيم.
نحسبو بالتواريخ
CURDATE(): تاريخ اليوم.YEAR(d)،MONTH(d)،DAY(d): العام، الشهر، النهار متاع تاريخ.DATEDIFF(d1, d2): عدد الأيام من d2 لـ d1.DATE_ADD(d, INTERVAL 7 DAY): سبعة أيام من بعد.
SELECT nom, YEAR(date_naissance) AS annee FROM eleve WHERE MONTH(date_naissance) >= 7;
بـ SQL
خدّم: الـ requête الأولى تخلّي التلامذة اللي فوق المعدّل العام. زيد requête تورّي اسم كل تلميذ والعمر متاعو بالأيام في 1 أكتوبر 2026 بـ DATEDIFF('2026-10-01', date_naissance).
CREATE TABLE classe (code VARCHAR(5) PRIMARY KEY, niveau VARCHAR(20) NOT NULL, salle VARCHAR(5));
CREATE TABLE eleve (
id INT PRIMARY KEY,
nom VARCHAR(30) NOT NULL,
code_classe VARCHAR(5),
moyenne DECIMAL(4,2),
date_naissance DATE,
FOREIGN KEY (code_classe) REFERENCES classe(code)
);
INSERT INTO classe VALUES ('4SI1', 'Bac SI', 'B12'), ('4SI2', 'Bac SI', 'B14'), ('3SI1', '3ème SI', 'A03');
INSERT INTO eleve VALUES
(1, 'Ben Salah', '4SI1', 12.50, '2008-03-14'),
(2, 'Trabelsi', '4SI1', 16.25, '2008-07-02'),
(3, 'Jaziri', '4SI2', 9.75, '2008-11-23'),
(4, 'Mansour', '4SI2', 14.00, '2007-12-30'),
(5, 'Bouzid', '3SI1', 11.00, '2009-05-05');
SELECT nom, moyenne FROM eleve
WHERE moyenne > (SELECT AVG(moyenne) FROM eleve);
SELECT nom FROM eleve
WHERE code_classe IN (SELECT code FROM classe WHERE niveau = 'Bac SI');
تدرّب مجانًا
كل درس فيه 3 تمارين مجانية مع تلميحات باش تطبّق الفصل هذا مع هنّيبوت.
← الفصل اللي قبل : استعلامات SQL بسيطة · الفصل اللي بعد : PHP: أوّل السكريبتات →
كل الفصول · شوف فروض 2 تكنولوجيا المصلّحة
الدروس كتبناها لـ Mission Carthage على أساس البرنامج الرسمي. الأستاذ متاعك يبقى المرجع.