Righe distinte con SQL (per chi SQL non lo mastica tanto)
Posted
mercoledì 28 febbraio 2007 14.12
by
francesco
Nel corso della mia attività di formatore in materia MS-Sql Server, non
è raro incontrare programmatori o sistemisti validissimi nel proprio lavoro, ma
con forti carenze di concetti di basi di dati nonché di linguaggio SQL.
Mentre nel caso di scarsa conoscenza di teoria di database, il cammino da
percorrere è spesso duro ed impervio, nel caso del linguaggio SQL, di solito
basta un po' di pratica e qualche buona dritta, daltronde è pur sempre un
linguaggio di programmazione.
A questo proposito, un classico dubbio che sorge in coloro che hanno poca
dimistichezza con SQL è quello legato alla presenza di duplicati in una tabella
così come in una query di selezione.
Premesso che il vincolo di chiave primaria o quello di unicità su una o più
colonne di una tabella, forniscano una risposta al primo dei due dubbi (la loro
presenza garantisce di fatto l'impossibilità di presenza di righe duplicate in
tabella), altro discorso va fatto relativamente a una query di selezione.
A differenza dell'algebra relazionale - ovvero la teoria matematica alla base
dei database relazionali - , SQL consente la presenza di duplicati nel risultato
di una proiezione (termine dell'algebra relazionale che indica una selezione di
tuple da una relazione, ovvero una selezione di righe da una tabella).
Di conseguenza spetta alla query di selezione eliminare le righe duplicate
sempre che il risultato non comprenda la chiave primaria o una colonna su cui
sia stato definito un vincolo di unicità, nel qual caso il risultato sarà già
privo di duplicati per definizione.
Vediamo un esempio.
USE
tempdb
GO
CREATE
TABLE Contatti (
Nome VARCHAR(30),
Cognome
VARCHAR(30),
CONSTRAINT PK_Contatti
PRIMARY KEY (Cognome, Nome)
)
INSERT
Contatti VALUES ('Francesco', 'Quaratino')
INSERT
Contatti VALUES ('Maurizio', 'Tammacco')
INSERT
Contatti VALUES ('Francesco', 'Totti')
INSERT
Contatti VALUES ('Maurizio', 'Vandelli')
SELECT
* FROM
Contatti
Per eliminare le righe duplicati dalla selezione, SQL mette a disposizione
l'attributo DISTINCT della SELECT.
SELECT DISTINCT Nome
FROM
Contatti
Oltre alla DISTINCT, ci sono altre operazioni che "indirettamente"
producono l'eliminazione dei duplicati.
Si tratta della GROUP BY e delle
operazioni insiemistiche UNION e EXCEPT.
GROUP BY ha lo scopo di raggruppare il risultato di una SELECT su un insieme
di colonne ordinate con la possibilità di applicare funzioni di raggruppamento
(per es. SUM(), AVG()) sul valore di una colonna sulla base del raggruppamento
applicato.
SELECT Nome, COUNT(Nome) FROM Contatti
GROUP
BY Nome
UNION ed EXCEPT sono due dei tre operatori insiemistici contemplati dallo
standard SQL (il terzo è INTERSECT).
Esse hanno lo scopo di agire come gli
operatori di UNIONE e DIFFERENZA sugli insiemi.
Proprio per la loro natura
insiemistica, tali operatori eliminano eventuali duplicati (ricordo che un
insieme è una collezione di oggetti distinti).
Per cui, con un piccolo
espediente potrebbero essere adoperatori a tale scopo.
L'espediente in
questione è una SELECT che non restituisca alcuna riga in virtù di una
condizione WHERE sempre falsa (per es. 0=1).
SELECT Nome FROM Contatti
UNION
SELECT
NULL WHERE
0=1
SELECT
Nome FROM Contatti
EXCEPT
SELECT
NULL WHERE
0=1