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

Filed under:

Comments

# re: Righe distinte con SQL (per chi SQL non lo mastica tanto)

giovedì 1 marzo 2007 1.48 by francesco

una precisazione: gli operatori insiemistici EXCEPT e INTERSECT oltre ad essere contemplati dallo standard SQL-92, sono prensenti a partire dalla versione 2005 di MS-Sql Server.