logo logo Dove iniziare Linguaggi Aiuto Blog
Home Dove iniziare Linguaggi Aiuto e Supporto Biadets Blog

JOIN in MySQL con Node.js

Finora abbiamo lavorato con singole tabelle. Tuttavia, nei database reali, i dati sono spesso distribuiti in più tabelle collegate tra loro. Ad esempio, in un e-commerce potremmo avere una tabella per gli utenti e una per gli ordini. Per combinare questi dati e ottenere informazioni complete, utilizziamo i JOIN.

Con Node.js e MySQL possiamo eseguire query JOIN per recuperare dati da più tabelle contemporaneamente, creando relazioni tra le informazioni.

Le relazioni tra tabelle

Prima di utilizzare i JOIN, è importante capire come le tabelle si collegano tra loro. Le tabelle sono collegate tramite chiavi:

  • Chiave primaria (PRIMARY KEY): identifica in modo univoco ogni riga di una tabella. Di solito è una colonna chiamata id.
  • Chiave esterna (FOREIGN KEY): è una colonna che fa riferimento alla chiave primaria di un'altra tabella, creando una relazione tra le tabelle.

Ad esempio, immaginiamo due tabelle:

Tabella utenti:

idnomeemail
1 Mario [email protected]
2 Luigi[email protected]

Tabella ordini:

idutente_idprodottoprezzo
1 1
Laptop 999.99
2 1
Mouse 29.99
3 2
Tastiera 79.99

Nella tabella ordini, la colonna utente_id è una chiave esterna che fa riferimento all'id della tabella utenti. Questo ci permette di sapere quale utente ha effettuato un ordine.

L'istruzione INNER JOIN

L'INNER JOIN è il tipo di JOIN più comune. Restituisce solo le righe in cui la condizione di JOIN è soddisfatta in entrambe le tabelle.

Vediamo come utilizzarlo in Node.js per ottenere tutti gli ordini con i dati degli utenti:

const sql = `SELECT ordini.id, ordini.prodotto, ordini.prezzo, utenti.nome, utenti.email
             FROM ordini
             INNER JOIN utenti ON ordini.utente_id = utenti.id;`;
  
con.query(sql, function (err, result) {
  if (err) throw err;
  console.log(result);
});

Nell'esempio:

  • Usiamo SELECT per specificare quali colonne vogliamo recuperare, come abbiamo visto nella lezione su SELECT. Per evitare ambiguità, scriviamo nomeTabella.nomeColonna.
  • FROM ordini indica la tabella principale da cui partiamo.
  • INNER JOIN utenti specifica la tabella da unire.
  • ON ordini.utente_id = utenti.id definisce la condizione di JOIN: colleghiamo le righe dove utente_id in ordini corrisponde a id in utenti.

Il risultato sarà un array contenente tutti gli ordini con i relativi dati dell'utente:

[
  { id: 1, prodotto: 'Laptop', prezzo: 999.99, nome: 'Mario', email: '[email protected]' },
  { id: 2, prodotto: 'Mouse', prezzo: 29.99, nome: 'Mario', email: '[email protected]' },
  { id: 3, prodotto: 'Tastiera', prezzo: 79.99, nome: 'Luigi', email: '[email protected]' }
]

Rinominare le tabelle

Quando lavoriamo con JOIN, le query possono diventare lunghe. Possiamo rinominare le tabelle con nomi più brevi o significativi per rendere il codice più leggibile. Utilizziamo la sintassi nome_tabella AS nuovo_nome.

const sql = `SELECT o.id, o.prodotto, o.prezzo, u.nome, u.email
             FROM ordini AS o
             INNER JOIN utenti AS u ON o.utente_id = u.id;`;

In questo caso, o è l'alias per ordini e u per utenti. Il risultato sarà identico, ma la query è più compatta.

LEFT JOIN

Il LEFT JOIN restituisce tutte le righe della tabella di sinistra (quella specificata in FROM) e le righe corrispondenti della tabella di destra. Se non c'è corrispondenza, i valori della tabella di destra saranno NULL.

Questo è utile quando vogliamo vedere tutti gli utenti, anche quelli che non hanno effettuato ordini:

const sql = `SELECT u.nome, u.email, o.prodotto, o.prezzo
             FROM utenti AS u
             LEFT JOIN ordini AS o ON u.id = o.utente_id;`;

con.query(sql, function (err, result) {
  if (err) throw err;
  console.log(result);
});

Se l'utente "Giacomo" (id:3) esiste nella tabella utenti ma non ha ordini, il risultato includerà:

{ nome: 'Giacomo', email: '[email protected]', prodotto: null, prezzo: null }

RIGHT JOIN

Il RIGHT JOIN è l'opposto del LEFT JOIN: restituisce tutte le righe della tabella di destra e le corrispondenze della tabella di sinistra. È meno comune del LEFT JOIN:

const sql = `SELECT u.nome, u.email, o.prodotto, o.prezzo
             FROM ordini AS o
             RIGHT JOIN utenti AS u ON o.utente_id = u.id;`;

Il risultato sarà simile al LEFT JOIN precedente. In questo caso, utenti è la tabella di destra, quindi otterremo tutti gli utenti anche se non hanno ordini.

Filtrare i dati dei JOIN

Possiamo utilizzare WHERE per filtrare i risultati di un JOIN, proprio come con le query normali:

const sql = `SELECT o.id, o.prodotto, o.prezzo, u.nome
             FROM ordini AS o
             INNER JOIN utenti AS u ON o.utente_id = u.id
             WHERE o.prezzo > 50;`;

con.query(sql, function (err, result) {
  if (err) throw err;
  console.log(result);
});

Questo restituirà solo gli ordini con prezzo superiore a 50, insieme ai dati dell'utente.

Ordinare i risultati

Possiamo anche utilizzare ORDER BY per ordinare i risultati, come abbiamo visto nella lezione sull'ordinamento dei dati:

const sql = `SELECT o.id, o.prodotto, o.prezzo, u.nome
             FROM ordini AS o
             INNER JOIN utenti AS u ON o.utente_id = u.id
             ORDER BY o.prezzo DESC;`;

I risultati saranno ordinati dal prezzo più alto al più basso.

Utilizzare i parametri con JOIN

Come sempre, quando utilizziamo valori provenienti dall'utente, dobbiamo usare parametri preparati per evitare SQL injection (come abbiamo visto meglio nella lezione sull'inserimento dei dati nel database):

const nomeUtente = "Mario";
const sql = `SELECT o.id, o.prodotto, o.prezzo, u.nome
             FROM ordini AS o
             INNER JOIN utenti AS u ON o.utente_id = u.id
             WHERE u.nome = ?;`;

con.query(sql, [nomeUtente], function (err, result) {
  if (err) throw err;
  console.log(result);
});

Il placeholder ? viene sostituito automaticamente con il valore di nomeUtente in modo sicuro.

Un esempio completo di JOIN

Vediamo un esempio completo che combina Express con MySQL per mostrare gli ordini di un utente:

const express = require("express");
const mysql = require("mysql");
const app = express();

const con = mysql.createConnection({
  host: "localhost",
  user: "root",
  password: "la_tua_password",
  database: "esempio"
});

con.connect(function (err) {
  if (err) throw err;
  console.log("Connesso al database");
});

app.get("/ordini/:utente_id", function (req, res) {
  const utenteId = req.params.utente_id;
  
  const sql = `SELECT o.id, o.prodotto, o.prezzo, u.nome, u.email
               FROM ordini AS o
               INNER JOIN utenti AS u ON o.utente_id = u.id
               WHERE u.id = ?;`;
  
  con.query(sql, [utenteId], function (err, result) {
    if (err) {
      res.send("Errore nel recupero degli ordini");
      return;
    }
    
    if (result.length === 0) {
      res.send("Nessun ordine trovato per questo utente");
      return;
    }
    
    res.json(result);
  });
});

app.listen(3000);

Visitando http://localhost:3000/ordini/1, si otterranno tutti gli ordini dell'utente con id 1 in formato JSON.

Prova!Completa gli spazi vuoti con il testo appropriato.
// Unisci la tabella ordini con la tabella utenti
SELECT o.prodotto, u.nome
FROM ordini AS o
utenti AS u ON o.utente_id = u.id;

Prova!Scegli l'opzione corretta tra quelle elencate.
// Quale tipo di JOIN mostra tutti gli utenti anche senza ordini?
SELECT u.nome, o.prodotto
FROM utenti AS u
____ ordini AS o ON u.id = o.utente_id;