πŸ—ƒοΈ Operatori Relazionali - Riassunto

Guida Completa con Esempi in MariaDB/MySQL

πŸ› οΈ Setup: Le Nostre Tabelle di Esempio

πŸ“‹ Scenario

Database con Studenti, Corsi e Esame (tabella di collegamento).

πŸ‘€ STUDENTI
idnomecittΓ etΓ 
1MarioRoma22
2LauraMilano20
3LucaRoma23
4AnnaNapoli21
πŸ“š CORSI
id_corsonome_corsodocente
101DatabaseRossi
102ProgrammazioneBianchi
103RetiVerdi
104YogaAldi
πŸ“ ESAME
id_studenteid_corsovoto
110128
110230
210125
310327
πŸ“œ SQL - Creazione Tabelle
-- Creazione del database
CREATE DATABASE IF NOT EXISTS universita;
USE universita;

CREATE TABLE studenti (
    id INT PRIMARY KEY,
    nome VARCHAR(50),
    citta VARCHAR(50),
    eta INT
);

CREATE TABLE corsi (
    id_corso INT PRIMARY KEY,
    nome_corso VARCHAR(50),
    docente VARCHAR(50)
);

CREATE TABLE ESAME (
    id_studente INT,
    id_corso INT,
    voto INT,
    PRIMARY KEY (id_studente, id_corso),
    FOREIGN KEY (id_studente) REFERENCES studenti(id),
    FOREIGN KEY (id_corso) REFERENCES corsi(id_corso)
);

πŸ“Œ Operatori Unari (su una sola tabella)

SELEZIONE (Οƒ - sigma)

πŸ“– Definizione

La selezione filtra le righe di una tabella in base a una condizione. Restituisce solo le tuple che soddisfano la condizione. Opera sulle RIGHE (orizzontalmente). Il numero di colonne resta invariato.

Οƒcondizione(Tabella)

🎯 Esempio: Studenti di Roma

STUDENTI
idnomecittΓ etΓ 
1MarioRoma22
2LauraMilano20
3LucaRoma23
4AnnaNapoli21
➜
βœ… RISULTATO
idnomecittΓ etΓ 
1MarioRoma22
3LucaRoma23
πŸ“œ MariaDB SQL
-- Selezione semplice
SELECT * FROM studenti WHERE citta = 'Roma';

-- Con AND: Roma E piΓΉ di 21 anni
SELECT * FROM studenti
WHERE citta = 'Roma' AND eta > 21;

-- Con OR / IN: Roma o Milano
SELECT * FROM studenti
WHERE citta IN ('Roma', 'Milano');

PROIEZIONE (Ο€ - pi)

πŸ“– Definizione

La proiezione seleziona solo alcune colonne dalla tabella, eliminando le altre. Opera sulle COLONNE (verticalmente). Il numero di righe puΓ² diminuire con DISTINCT.

Ο€colonna1, colonna2(Tabella)

🎯 Esempio: Solo nome e città degli studenti

βœ… RISULTATO
nomecittΓ 
MarioRoma
LauraMilano
LucaRoma
AnnaNapoli
πŸ“œ MariaDB SQL
-- Proiezione semplice
SELECT nome, citta FROM studenti;

-- Eliminare duplicati (come in algebra relazionale)
SELECT DISTINCT citta FROM studenti;
-- Risultato: Roma, Milano, Napoli (3 righe, non 4)

-- Combinazione Selezione + Proiezione: Οƒ cittΓ ='Roma' β†’ Ο€ nome
SELECT nome FROM studenti WHERE citta = 'Roma';

πŸ”— Prodotto Cartesiano e JOIN

PRODOTTO CARTESIANO (Γ—)

πŸ“– Definizione

Combina ogni riga della prima tabella con ogni riga della seconda. Genera tutte le combinazioni possibili. Il computer non sa quali righe appartengono a chi: sarΓ  poi compito del JOIN filtrare solo quelle dove gli ID corrispondono.

Studenti Γ— ESAMI
STUDENTI
idnome
1Mario
2Laura
Γ—
ESAMI
id_studentevoto
128
230
RISULTATO (2 Γ— 2 = 4 righe)
idnomeid_studentevoto
1Mario128
1Mario230
2Laura128
2Laura230
πŸ‘€ Chiave

Il JOIN Γ¨ un Prodotto Cartesiano filtrato: elimina le righe dove gli ID non corrispondono e tiene solo quelle valide.

πŸ“œ MariaDB SQL
SELECT * FROM studenti CROSS JOIN esami;

INNER JOIN (Theta Join / Equi-Join) β‹ˆ

πŸ“– Definizione

Prodotto cartesiano filtrato da una condizione. Restituisce solo le righe dove la condizione Γ¨ soddisfatta. JOIN e INNER JOIN sono equivalenti (la parola INNER Γ¨ opzionale).

Tabella1 β‹ˆcondizione Tabella2

πŸ“Œ Esempio 1: Join Base (Studenti β†’ Esami)

βœ… RISULTATO INNER JOIN (id = id_studente)
idnomeid_studenteid_corsovoto
1Mario110128
1Mario110230
2Laura210125
3Luca310327
πŸ‘€ Nota

Anna (id=4) non appare perchΓ© non ha esami. Mario appare 2 volte perchΓ© ha 2 esami.

πŸ“œ MariaDB SQL
-- INNER JOIN base
SELECT *
FROM studenti s
INNER JOIN esami e ON s.id = e.id_studente;

-- Equivalente (JOIN senza INNER = stesso risultato)
SELECT *
FROM studenti s
JOIN esami e ON s.id = e.id_studente;

πŸ“Œ Esempio 2: Join tra 3 Tabelle

🎯 Nome studente, nome corso e voto (3 tabelle collegate).

πŸ“œ MariaDB SQL
SELECT s.nome, c.nome_corso, e.voto
FROM studenti s
JOIN esami e ON s.id = e.id_studente
JOIN corsi c ON e.id_corso = c.id;

πŸ“Œ Esempio 3: Join con Condizioni Multiple (AND)

🎯 Abbinare dipendenti ai turni per reparto E sede.

πŸ“œ MariaDB SQL
-- Join su DUE colonne per evitare errori
SELECT d.nome, d.reparto, d.sede, t.giorno, t.orario
FROM dipendenti d
JOIN turni t
    ON d.reparto = t.reparto
    AND d.sede = t.sede;

πŸ“Œ Esempio 4: Theta Join (condizione β‰  uguaglianza)

🎯 Prodotti nel budget del cliente (budget β‰₯ prezzo). Il Theta Join usa qualsiasi operatore (=, <, >, <=, >=, <>, LIKE, BETWEEN). L'Equi-Join Γ¨ il caso particolare con "=".

πŸ“œ MariaDB SQL
SELECT c.nome AS cliente, c.budget, p.nome AS prodotto, p.prezzo
FROM clienti c
JOIN prodotti p ON c.budget >= p.prezzo;

πŸ“Œ Esempio 5: Join + Filtro WHERE

⚠️ ON vs WHERE

ON: condizione per collegare le tabelle (relazione) | WHERE: filtro sui risultati (selezione)

πŸ“œ MariaDB SQL
-- Esami con voto >= 28 di studenti il cui nome inizia per 'M'
SELECT s.nome, e.voto
FROM studenti s
JOIN esami e ON s.id = e.id_studente
WHERE s.nome LIKE 'M%'
  AND e.voto >= 28;

LEFT JOIN βŸ•

πŸ“– Definizione

Restituisce tutte le righe della tabella di SINISTRA + le corrispondenze dalla destra. Se non c'Γ¨ corrispondenza, le colonne della destra sono NULL.

🎯 Esempio: Tutti gli studenti CON i loro esami (anche chi non ha esami)

βœ… RISULTATO LEFT JOIN
idnomeid_corsovoto
1Mario10128
1Mario10230
2Laura10125
3Luca10327
4AnnaNULLNULL
πŸ‘€ Nota

Anna appare! Anche senza esami, viene inclusa con NULL perchΓ© Γ¨ nella tabella di SINISTRA.

πŸ“œ MariaDB SQL
-- LEFT JOIN: tutti gli studenti, anche senza esami
SELECT s.id, s.nome, i.id_corso, i.voto
FROM studenti s
LEFT JOIN iscrizioni i ON s.id = i.id_studente;

-- Trovare studenti SENZA esami (filtro su NULL)
SELECT s.*
FROM studenti s
LEFT JOIN iscrizioni i ON s.id = i.id_studente
WHERE i.id_studente IS NULL;

RIGHT JOIN βŸ–

πŸ“– Definizione

Restituisce tutte le righe della tabella di DESTRA + le corrispondenze dalla sinistra. Se non c'Γ¨ corrispondenza, le colonne della sinistra sono NULL.

🎯 Esempio: Tutti i corsi con chi è iscritto (incluso Yoga senza iscritti)

βœ… RISULTATO RIGHT JOIN
nome_corsoid_studentevoto
Database128
Database225
Programmazione130
Reti327
YogaNULLNULL
πŸ“œ MariaDB SQL
-- RIGHT JOIN: tutti i corsi, anche senza iscritti
SELECT c.nome_corso, i.id_studente, i.voto
FROM iscrizioni i
RIGHT JOIN corsi c ON i.id_corso = c.id_corso;

-- Equivalente: LEFT JOIN invertendo l'ordine delle tabelle
SELECT c.nome_corso, i.id_studente, i.voto
FROM corsi c
LEFT JOIN iscrizioni i ON c.id_corso = i.id_corso;
πŸ’‘ Consiglio Pratico

Scrivere iscrizioni RIGHT JOIN corsi Γ¨ identico a scrivere corsi LEFT JOIN iscrizioni. In entrambi i casi il risultato contiene tutti i corsi (incluso Yoga) + le iscrizioni abbinate.

Per questo motivo, molti programmatori preferiscono usare sempre LEFT JOIN e, quando servirebbe RIGHT JOIN, invertono semplicemente l'ordine delle tabelle: invece di A RIGHT JOIN B scrivono B LEFT JOIN A β€” il risultato Γ¨ identico ma la query Γ¨ piΓΉ leggibile.

FULL JOIN βŸ—

πŸ“– Definizione

Restituisce tutte le righe di ENTRAMBE le tabelle. Se non c'Γ¨ corrispondenza, le colonne mancanti sono NULL. Nessun dato viene perso!

⚠️ MariaDB/MySQL NON supporta FULL JOIN!

Si simula con UNION di LEFT JOIN e RIGHT JOIN.

πŸ“œ MariaDB SQL - Simulazione FULL JOIN
SELECT s.id, s.nome, i.id_studente, i.id_corso, i.voto
FROM studenti s
LEFT JOIN iscrizioni i ON s.id = i.id_studente
UNION
SELECT s.id, s.nome, i.id_studente, i.id_corso, i.voto
FROM studenti s
RIGHT JOIN iscrizioni i ON s.id = i.id_studente;

-- In altri DBMS: SELECT * FROM studenti s FULL OUTER JOIN iscrizioni i ON s.id = i.id_studente;

πŸ“Š Riepilogo dei JOIN

JOIN

Solo righe con match in entrambe

LEFT JOIN

Tutto A + match da B (o NULL)

RIGHT JOIN

Match da A (o NULL) + tutto B

FULL JOIN

Tutto A + match + tutto B

NATURAL JOIN - Alternativa a JOIN...ON...

πŸ“– Definizione

Join automatico (non serve ON): unisce le tabelle basandosi sulle colonne con lo stesso nome. Elimina automaticamente le colonne duplicate.

πŸ“œ MariaDB SQL
-- NATURAL JOIN: unisce automaticamente sulle colonne con lo stesso nome
SELECT * FROM studenti NATURAL JOIN voti;
-- Equivale a: JOIN voti ON studenti.id = voti.id
⚠️ Perché Evitare NATURAL JOIN
ProblemaConseguenza
Colonne omonime per coincidenzaJoin su campi non correlati β†’ risultati vuoti o errati
Schema che evolveQuery funzionanti oggi si rompono domani senza preavviso
Perdita dati silenziosaRighe escluse senza errori, impossibile debuggare
Mancanza di chiarezzaImpossibile capire su quali colonne avviene il join leggendo la query
βœ… Best Practice

Usa sempre JOIN esplicito con ON: Γ¨ piΓΉ verboso ma chiaro, prevedibile, manutenibile e sicuro.

Clausola USING - Alternativa a ON

πŸ“– Definizione

Alternativa a ON per specificare le condizioni di join quando le colonne di collegamento hanno lo stesso nome in entrambe le tabelle. La colonna appare una sola volta nel risultato (piΓΉ pulito).

⚠️ Attenzione: nomi diversi β†’ niente USING!

Nel nostro setup, la tabella ESAME ha la colonna id_studente (chiave esterna), mentre STUDENTI ha id (chiave primaria). Avendo nomi diversi, USING non puΓ² essere usato β€” bisogna usare ON:

❌ Il nostro setup: nomi diversi β†’ OBBLIGATORIO usare ON
-- STUDENTI ha la colonna "id", ESAME ha la colonna "id_studente"
-- I nomi sono diversi β†’ non si puΓ² usare USING, serve ON
SELECT *
FROM studenti s
JOIN esame e ON s.id = e.id_studente;

πŸ“Œ Quando USING funziona: colonne con lo STESSO nome

Se entrambe le tabelle hanno una colonna chiamata id che si riferisce alla stessa entitΓ  (es. l'id dello studente), allora USING Γ¨ piΓΉ pulito:

STUDENTI
idnome
1Mario
2Laura

id = chiave primaria dello studente

VOTI
idvoto
128
130

id = chiave esterna β†’ studente (stesso significato!)

βš–οΈ ON vs USING: confronto visivo

πŸ”΄ Risultato con ON

studenti.idnomevoti.idvoto
1Mario128

❌ La colonna id appare due volte (valori identici β†’ ridondanza)

🟒 Risultato con USING

idnomevoto
1Mario28

βœ… La colonna id appare una sola volta β†’ piΓΉ pulito

πŸ“œ MariaDB SQL
-- Metodo 1: JOIN con ON (funziona sempre, anche con nomi diversi)
SELECT * FROM studenti
JOIN voti ON studenti.id = voti.id;

-- Metodo 2: JOIN con USING (solo se la colonna ha lo STESSO nome in entrambe le tabelle)
SELECT * FROM studenti
JOIN voti USING (id);

-- USING con LEFT JOIN
SELECT * FROM studenti LEFT JOIN voti USING (id);

-- USING con PIΓ™ colonne (se entrambe le tabelle hanno col1 e col2)
SELECT * FROM tabella1
JOIN tabella2 USING (colonna1, colonna2);
πŸ“‹ Quando Usare Cosa
ScenarioClausola
Colonne con nomi diversi (es. id vs id_studente)❌ ON (obbligatorio β€” USING darebbe errore)
Colonne con stesso nome e stesso significatoβœ… USING (piΓΉ pulito)
Condizioni complesse (AND/OR)❌ ON (necessario)
Evitare colonne duplicate nel risultatoβœ… USING (colonna mostrata una sola volta)

🎯 Operazioni Insiemistiche

πŸ“‹ Requisito Fondamentale

Per UNION, INTERSECT e EXCEPT le tabelle devono essere union-compatibili: stesso numero di colonne e tipi compatibili.

STUDENTI_ROMA
idnome
1Mario
3Luca
STUDENTI_DB
idnome
1Mario
2Laura

UNIONE (βˆͺ - UNION)

πŸ“– Definizione

Combina i risultati di due query, restituendo tutte le righe di entrambe senza duplicati (per default).

A βˆͺ B
STUDENTI_ROMA
idnome
1Mario
3Luca
βˆͺ
STUDENTI_DB
idnome
1Mario
2Laura
=
RISULTATO
idnome
1Mario
2Laura
3Luca
πŸ“œ MariaDB SQL
-- UNION: senza duplicati
SELECT * FROM studenti_roma
UNION
SELECT * FROM studenti_db;

-- UNION ALL: mantenendo i duplicati (Mario appare 2 volte)
SELECT * FROM studenti_roma
UNION ALL
SELECT * FROM studenti_db;

INTERSEZIONE (∩ - INTERSECT)

πŸ“– Definizione

Restituisce solo le righe che appaiono in entrambe le query.

A ∩ B
STUDENTI_ROMA
idnome
1Mario
3Luca
∩
STUDENTI_DB
idnome
1Mario
2Laura
=
RISULTATO
idnome
1Mario
⚠️ MariaDB NON supporta INTERSECT direttamente!

Si simula con JOIN o subquery.

πŸ“œ MariaDB SQL - Simulazione INTERSECT
-- Con IN: trova studenti presenti in ENTRAMBE le tabelle
SELECT * FROM studenti_roma
WHERE id IN (SELECT id FROM studenti_db);

-- Con JOIN: alternativa piΓΉ efficiente
SELECT a.* FROM studenti_roma a
JOIN studenti_db b ON a.id = b.id;

DIFFERENZA (βˆ’ - EXCEPT)

πŸ“– Definizione

Restituisce le righe che sono nella prima tabella ma NON nella seconda.

A βˆ’ B
STUDENTI_ROMA
idnome
1Mario
3Luca
βˆ’
STUDENTI_DB
idnome
1Mario
2Laura
=
RISULTATO
idnome
3Luca
⚠️ MariaDB NON supporta EXCEPT direttamente!

Si simula con LEFT JOIN + WHERE NULL o NOT IN.

πŸ“œ MariaDB SQL - Simulazione EXCEPT
-- Con NOT IN: studenti presenti SOLO nella prima tabella
SELECT * FROM studenti_roma
WHERE id NOT IN (SELECT id FROM studenti_db);

-- Con LEFT JOIN + IS NULL: alternativa piΓΉ efficiente
SELECT a.* FROM studenti_roma a
LEFT JOIN studenti_db b ON a.id = b.id
WHERE b.id IS NULL;
↑