[SQL] dubbio sintassi ed uso di prodotto cartesiano e join

Forum dedicato alla programmazione.

Moderatore: Staff

Regole del forum
1) Citare in modo preciso il linguaggio di programmazione usato.
2) Se possibile portare un esempio del risultato atteso.
3) Leggere attentamente le risposte ricevute.
4) Scrivere i messaggi con il colore di default, evitare altri colori.
5) Scrivere in Italiano o in Inglese, se possibile grammaticalmente corretto, evitate stili di scrittura poco chiari, quindi nessuna abbreviazione tipo telegramma o scrittura stile SMS o CHAT.
6) Appena registrati è consigliato presentarsi nel forum dedicato.

La non osservanza delle regole porta a provvedimenti di vari tipo da parte dello staff, in particolare la non osservanza della regola 5 porta alla cancellazione del post e alla segnalazione dell'utente. In caso di recidività l'utente rischia il ban temporaneo.
Rispondi
Avatar utente
sberla54
Master
Master
Messaggi: 1500
Iscritto il: gio 24 giu 2004, 0:00
Slackware: 13.0
Desktop: Gnome (o Fluxbox)
Distribuzione: Ubuntu
Località: Bologna
Contatta:

[SQL] dubbio sintassi ed uso di prodotto cartesiano e join

Messaggio da sberla54 »

Ciao ragazzi.
Sara' sicuramente una cavolata ma non sto riuscendo a capire la differenza tra il prodotto cartesiano (cross join) ed il join semplice (che credo sia il join interno), quello con sintassi

Codice: Seleziona tutto

SELECT qualcosa
FROM tabella1 JOIN tabella2 ON chiave1 = chiave2
WHERE condizione
Anzi, per essere piu' precisi, non riesco a capire se le interrogazioni espesse con la sintassi

Codice: Seleziona tutto

SELECT qualcosa
FROM tabella1 AS tab1, tabella2 AS tab2
WHERE tab1.chiave1 = tab2.chiave2
sono prodotti cartesiani oppure semplici join (interni?) espressi con una sintassi semplificata ed utilizzando il WHERE al posto di ON per specificare tramite quali campi chiave le 2 tabelle devono essere joinate.

Ho notato che negli ultimi appelli della mia facolta', come ad esempio quello del 20.01.2009 (che allego in fondo al topic), la maggior parte delle query SQL vengono risolte utilizzando la sintassi con le virgole, anche se a me verrebbe naturale utilizzare la sintassi con JOIN.
Ad esempio, l'esercizio 3.B dell'appello del 20.01.2009 richiede: "Selezionare in SQL i cognomi delle persone che spendonp piu' di 700 euro in corsi"
e viene risolta con:

Codice: Seleziona tutto

SELECT P.Cognome
FROM Persona P, Iscrizione I, Corso C
WHERE P.ID = I.Persona AND I.Corso = C.Nome
GROUP BY ID, Cognome
HAVING SUM(Prezzo) > 700
Tutto questo e' un semplice join tra Persona, Iscrizione e Corso, in cui Persona e Iscrizione sono legati ON Persona.ID = Iscrizione.Persona, mentre Iscrizion e Corso sono legati ON Iscrizione.Corso = Corso.Nome?
Oppure e' qualcosa di diverso?

Io l'avrei scritta cosi:

Codice: Seleziona tutto

SELECT P.Cognome
FROM Persona P JOIN Iscrizione I ON P.ID = I.Persona JOIN Corso C ON I.Corso = C.Nome
GROUP BY ID, Cognome
HAVING SUM(Prezzo) > 700
oppure:

Codice: Seleziona tutto

SELECT Cognome
FROM Persona JOIN Iscrizione ON Persona.ID = Iscrizione.Persona JOIN Corso ON Iscrizione.Corso = Corso.Nome
GROUP BY ID, Cognome
HAVING SUM(Prezzo) > 700
Non e' la stessa identica cosa?

Ho trovato questa guida secondo la quale le due sintassi sono equivalenti...o almeno cosi' credo di aver capito: http://database.html.it/guide/lezione/2 ... elle-join/

Cito alcuni pezzi:
La inner join si effettua andando a cercare righe corrispondenti nelle due tabelle, basandosi sul valore di determinate colonne.
Immaginiamo, in un esempio classico, di avere una tabella ordini e una tabella clienti. Diciamo che la prima contiene le colonne idOrdine, idCliente, articolo, quantità mentre la seconda contiene idCliente, nome, cognome.
Evidentemente il campo 'idCliente' della tabella ordini è una chiave esterna sulla tabella clienti, che ci permette di recuperare i dati anagrafici del cliente che ha effettuato l'ordine (abbiamo limitato al minimo, per semplicità, il numero dei campi contenuti nelle due tabelle). In questo caso quindi potremo fare le join basandoci sulla corrispondenza dei valori dei campi 'idCliente' nelle due tabelle (naturalmente non è necessario che le colonne abbiano lo stesso nome).
Vediamo alcuni esempi:

SELECT * FROM ordini AS o, clienti AS c WHERE o.idCliente = c.idCliente AND idOrdine > 1000;

SELECT * FROM ordini AS o JOIN clienti AS c on o.idCliente = c.idCliente WHERE idOrdine > 1000;

Queste due query sono equivalenti e rappresentano una inner join: estraggono i dati relativi ad ordine e cliente per quegli ordini che hanno un identificativo maggiore di 1000. La prima è una join implicita: infatti non l'abbiamo dichiarata esplicitamente e abbiamo messo la condizione di join nella clausola WHERE. Quando elenchiamo più tabelle nella FROM senza dichiarare esplicitamente la JOIN stiamo facendo una inner join (oppure una cross join se non indichiamo condizioni di join nella WHERE).
Nella seconda, al posto di 'JOIN' avremmo potuto scrivere per esteso 'INNER JOIN'; in alcune vecchie versioni di MySQL ciò è obbligatorio.
SELECT * FROM ordini as o LEFT JOIN clienti as c ON o.idCliente = c.idCliente WHERE idOrdine > 1000;
Quindi a me verrebbe da pensare che la sintassi con le virgole si puo' utilizzare, per comodita' (anche se la trovo piu' complicata), quando il campo WHERE non deve essere usato per una condizione che riduca l'output della query, e viene usato invece essere usato per indicare le chiavi tramite cui joinare le tabelle; la sintassi col JOIN invece va utilizzata quando il campo WHERE ci serve ai fini del risultato della query.

Ho pensato anche che la sintassi con le virgole rappresenti il prodotto cartesiano quando le tabelle non hanno delle colonne in comune (intendo con dati in comune, ad esempio Cliente.ID e Abbonamento.Cliente) e quindi non e' comunque possibile joinarle.
In questo caso il campo WHERE rimarrebbe libero per essere usato per la condizione della query.
Se il campo WHERE collega delle chiavi allora e' un join

Vaneggio? :)

Virgole e JOIN sono esattamente la stessa cosa o sono due cose completamente diverse?

E'giusto il mio ragionamento sul campo WHERE usato al posto della specifica ON per indicare le chiavi da usare per il join?

Il prodotto cartesiano (cross join) quando va usato? A me sembre che negli esercizi sia sempre possibile utilizzare il JOIN...

Ed infine, quando si usa il termine JOIN senza specifiche ulteriori, di che tipo di JOIN si tratta? Del join interno come dice la guida di html.it?

Non e' che qualcuno di voi ha qualche link un po' piu' comprensibile su questo argomento?

Spero che sappiate aiutarmi almeno voi; ho chiesto un po' in giro ma ogni volta ricevo una versione diversa.
Sono gia' diversi giorni che mi ci sto confondendo ed e' veramente fondamentale che io riesca a capire chiaramente la differenza fra le varie sintassi ed i vari join da utilizzare negli esercizi.

Grazie!

Appello 2009.01.20, parte SQL
Immagine

Avatar utente
nuitari
Linux 3.x
Linux 3.x
Messaggi: 777
Iscritto il: dom 14 ott 2007, 12:51
Slackware: 12.0
Località: San Colombano al Lambro
Contatta:

Re: [SQL] dubbio sintassi ed uso di prodotto cartesiano e join

Messaggio da nuitari »

Eheh la risposta è... sono entrambi un inner join (ogni record di A per ogni record di B che soddisfano la condizione .

il linguaggio SQL permette di utilizzare due differenti sintassi per gli inner join, la sintassi esplicita e quella implicita.

La sintassi esplicita viene fatta usando la clausola inner e restituisce tutti i record che corrispondono al predicato ON.
La sintassi implicita usa la forma *elenco di tabelle separate da virgole* nella clausola FROM, che di per se specificano un cross join, cui viene applicato un filtro con la clausola WHERE (risultato: inner join. in questo senso influiscono molto le ottimizzasioni del query optimizer).

Il prodotto cartesiano di due tabelle è l'algoritmo (vecchio, ci sono meccanismi + efficienti) che viene utilizzato per recuperare il set di dati su cui effettuare i vari tipi di join e predicati/filtri. Si tratta quasi sempre di un risultato intermedio, tranne nel caso di un cross join esplicito/implicito.

elendil
Linux 1.x
Linux 1.x
Messaggi: 103
Iscritto il: sab 9 ago 2008, 12:39
Nome Cognome: Valerio
Slackware: 14
Kernel: 3.2.29
Desktop: xfce
Distribuzione: SalixOS
Località: Carpineto Romano (RM)

Re: [SQL] dubbio sintassi ed uso di prodotto cartesiano e join

Messaggio da elendil »

Sono di corsa e ho dato uno sguardo alla prima parte del tuo post... Ho le conoscenze delle basi di dati e di SQL un pò arruginite, quindi spero di non scrivere cavolate, ma se non ricordo male il risultato del join è un sottoinsieme del prodotto cartesiano. Il prodotto cartesiano (rozzamente) tra due insieme A e B è l'insieme di tutte le coppie <a,b> formate dagli elementi di tutti e due gli insiemi, mentre l'operazione di join permette di "selezionare" le coppie che vogliamo nel specificando una condizione. I primi due pezzi di codice che hai messo non sono due prodotti cartesiani, ma due casi di equi-join e rappresentano la stessa query. SQL è un linguaggio molto ricco e i DBMS che trovi in giro (anche commerciali tipo Oracle) non supportano tutte le opzioni che SQL mette a disposizione, quindi scrivere query nel modo più "compatibile" possibile è una buona pratica per poterle usare su altri DBMS. Io personalmente preferisco questo:

Codice: Seleziona tutto

SELECT qualcosa
FROM tabella1 AS tab1, tabella2 AS tab2
WHERE tab1.chiave1 = tab2.chiave2
Negli esercizi tipicamente userai sempre il JOIN e ti consiglio di usare la sintassi che ti viene più naturale ;)
"In wars boy, fools kill other fools for foolish causes." (R. Jordan, The Wheel of Time book 1)

Avatar utente
sberla54
Master
Master
Messaggi: 1500
Iscritto il: gio 24 giu 2004, 0:00
Slackware: 13.0
Desktop: Gnome (o Fluxbox)
Distribuzione: Ubuntu
Località: Bologna
Contatta:

Re: [SQL] dubbio sintassi ed uso di prodotto cartesiano e join

Messaggio da sberla54 »

Eheh la risposta è... sono entrambi un inner join (ogni record di A per ogni record di B che soddisfano la condizione .
il linguaggio SQL permette di utilizzare due differenti sintassi per gli inner join, la sintassi esplicita e quella implicita.

[...]

La sintassi esplicita viene fatta usando la clausola inner e restituisce tutti i record che corrispondono al predicato ON.
La sintassi implicita usa la forma *elenco di tabelle separate da virgole* nella clausola FROM, che di per se specificano un cross join, cui viene applicato un filtro con la clausola WHERE (risultato: inner join. in questo senso influiscono molto le ottimizzasioni del query optimizer).
Grande, come l'avevo intuita io! Grazie!
Ho le conoscenze delle basi di dati e di SQL un pò arruginite, quindi spero di non scrivere cavolate, ma se non ricordo male il risultato del join è un sottoinsieme del prodotto cartesiano. Il prodotto cartesiano (rozzamente) tra due insieme A e B è l'insieme di tutte le coppie <a,b> formate dagli elementi di tutti e due gli insiemi, mentre l'operazione di join permette di "selezionare" le coppie che vogliamo nel specificando una condizione. I primi due pezzi di codice che hai messo non sono due prodotti cartesiani, ma due casi di equi-join e rappresentano la stessa query.
Ottimo.
Grazie ad entrambi :)

Rispondi