![]() |
MINI CORSO DI MICROSOFT ACCESS - parte 3° |
![]() |
Con questo pannello vengono create le interrogazioni e gli
ordinamenti sugli
archivi. Rappresenta lo strumento di analisi dei dati.
Alla base delle interrogazioni abbiamo un linguaggio
chiamato SQL
QUERY DI SELEZIONE
Le Query di selezione consentono:
- di estrarre da una tabella solo alcune colonne
- la creazione di elenchi ordinati
-
di selezionare, da una tabella, solo alcune righe in base alle condizioni
specificate nella query stessa.
CREAZIONE DI UNA QUERY
Partendo dal ribbon "Crea" andiamo nella
sezione "Query" e clicchiamo sull'icona
Viene proposto l’elenco delle Tabelle o delle Query disponibili
Facciamo doppio click su ogni tabella coinvolta nella nostra
query
Per selezionare i campi da visualizzare basta fare doppio click sul campo della tabella interessata (Zona A). Il primo posto disponibile nella zona B verrà occupato dal campo selezionato.
Notare lo * presente nella
prima riga di ogni tabella. Se seleziono questa
voce indico che di quella tabella intendo visualizzare tutti i campi.
Per eseguire una query basta cliccare sul bottone
"Esegui" nel ribbon "Progettazione" / "Strumenti
Query"
La zona B contiene l'elenco dei campi che la query
visualizza
Analizziamo in dettaglio le singole voci di questa sezione:
Campo: In questa riga vengono
indicati i campi da visualizzare.
Tabella: Le query possono
coinvolgere più tabelle. Qui si specifica da quale tabella il campo selezionato
è
prelevato
Ordinamento:
con questa proprietà possiamo impostare se l'elenco (ottenuto con la query)
debba essere ordinato in maniera crescente
o decrescente rispetto al campo associato a quella colonna. L’ordinamento è uno dei principali motivi per cui
si utilizzano
le query.
Se intendo ordinare un elenco rispetto a più campi (es.
elenco degli studenti per classe e per cognome) devo tener presente che il campo
che
viene ordinato per primo è quello che si trova più a sinistra. L’ordine dei
campi che determinano l'ordinamento è quindi importante.
Nell'esempio qua sopra ordino l'elenco degli studenti prima per classe e poi, all'interno di ogni classe, per cognome.
In OpenOffice Base la stessa query all'interno dell'interfaccia grafica si presenta in questo modo:
Mostra: questa riga consente di nascondere il campo durante l'esecuzione della query. Solitamente viene utilizzato quando devo selezionare dei campi che risultano necessari:
- per specificare gli ordinamenti
- per definire le condizioni di selezione
e
che non intendo visualizzare.
Esempio 1: Ho una query che si chiama "Clienti di Brescia". Nella struttura di questa query avremo un vincolo per cui il campo "Provincia" deve essere pari alla stringa 'Brescia'. Visualizzare il nome della provincia durante l'esecuzione della Query è inutile poichè il nome della Query stessa è eloquente. Pertanto posso evitare di mostrare il campo provincia.
Esempio 2: Un altro caso dove questa proprietà è importante si ha quando l'ordine di visualizzazione dei campi è differente dall'ordine dei campi che determinano un ordinamento.
Esempio: devo ottenere un elenco di studenti dove il Nome appare in 1^ colonna, il Cognome in 2^ colonna e la Classe in 3^. L'ordinamento di questo elenco prevede prima la Classe e poi il Cognome.
Per accedere al pannello di scrittura dei comandi SQL basta andare sulla barra del titolo di una query e richiamare mediante il tasto destro la voce "Visualizzazione SQL" del menu contestuale.
In OpenBase basta utilizzare, nel pannello "Ricerche", la voce
"Crea ricerca in vista SQL ..."
![]() |
Menu equivalente di OpenOffice Base |
Immaginiamo di avere a disposizione una tabella CLIENTI con questi campi (in figura sono mostrate le definizioni della tabella CLIENTI con Microsoft Access e con OpenOffice Base)
![]() |
![]() |
definizione con Microsoft Access | definizione con OpenOffice Base 3.2 |
Qui sotto i comandi VBA per ricreare la tabella e i dati in Access
Public Function CreaDB() Dim CmdSQL As String On Error Resume Next CurrentDb.Execute ("DROP TABLE Clienti") On Error GoTo 0 CurrentDb.Execute("CREATE TABLE Clienti" & _ "(" & _ " IdCliente LONG CONSTRAINT IdCliIdx PRIMARY KEY," & _ " [Ragione Sociale] TEXT(50) CONSTRAINT RagSocIdx NOT NULL, " & _ " Prov TEXT(2), " & _ " Fatturato SINGLE, " & _ " DataRag DateTime " & _ ");") CurrentDb.Execute ("INSERT INTO Clienti VALUES (1,'Rossi Spa','BS',1000.21,#01/03/1964#);") CurrentDb.Execute ("INSERT INTO Clienti VALUES (2,'Verdi Srl','BG',390,#03/01/1981#);") CurrentDb.Execute ("INSERT INTO Clienti VALUES (3,'Gialli Snc','BS',7291,#03/01/1980#);") CurrentDb.Execute ("INSERT INTO Clienti VALUES (4,'La Ruspa Srl','BS',123,#03/01/2001#);") CurrentDb.Execute ("INSERT INTO Clienti VALUES (5,'Neri Spa','TN',23.29,#03/01/1999#);") CurrentDb.Execute ("INSERT INTO Clienti VALUES (6,'Ipermercato Snc','BG',129.03,#02/29/2000#);") CurrentDb.Execute ("INSERT INTO Clienti VALUES (7,'Casa Rotta Snc','BG',339.93,#03/28/2000#);") CurrentDb.Execute ("INSERT INTO Clienti VALUES (8,'Bianchi Sas','TN',23.29,#03/01/1999#);") CurrentDb.Execute ("INSERT INTO Clienti VALUES (9,'Rosa Camuna Spa','BS',1003.9,#03/12/2001#);") End Function
Per eseguire il codice seguire questi passaggi:
a) premi la combinazione alt-F11;
b) menu "inserisci"
voce "modulo";
c) incolla nella finestra tutto il codice VBA;
d) premi la combinazione Ctrl+G;
e) digita
call CreaDB e batti
invio;
f)
chiudi Access senza salvare e riaprilo oppure vai nel pannello delle "tabelle"
e premi F5.
Clicca qui per scaricare invece il file di OpenBase.
LE QUERY DI SELEZIONE
ORDINAMENTI |
Esempio 1:
Questo comando visualizza per intero la tabella clienti
SELECT è il comando SQL utilizzato per estrarre i
dati (tipico delle query di selezione).
Esempio 2:
SELECT [Ragione Sociale] FROM CLIENTI
Estrae l’elenco delle ragioni sociale
OpenOffice Base utilizza come delimitatore per i nomi dei campi sia il doppio apice (") che l'apice inverso (si ottiene componendo il numero 96 con il tastierino numerico e premendo contemporaneamente il tasto ALT). Quindi in OpenOffice Base il comando SQL
SELECT IdClienti, `Ragione Sociale` FROM Clienti
è equivalente a:
SELECT IdClienti, "Ragione Sociale" FROM Clienti
Esempio 3
SELECT [Ragione Sociale] AS NomeDitta FROM CLIENTI
Visualizza l’elenco delle ragioni sociali modificando l’intestazione del campo in NomeDitta. Le query consentono quindi di modificare in visualizzazione i nomi dei campi originali. Rinominare serve a rendere + comprensibile il contenuto dei risultati di una query. Si pensi ad un utente straniero che deve utilizzare il nostro archivio "Clienti". La parola ragione sociale per lui è chiaramente incomprensibile. Utilizzando questa tecnica posso creare degli elenchi con le intestazioni nella lingua dell’utente che dovrà consultare i nostri archivi rendendoli così comprensivi.
Esempio
4
SELECT
[Ragione Sociale] AS Azienda, Prov FROM CLIENTI ORDER BY PROV
Elenca i clienti visualizzando il nome della ditta e la loro
provincia il tutto ordinato per
provincia.
La parola chiave ORDER BY viene utilizzata per specificare i
campi da ordinare.
Qualora i campi da ordinare fossero diversi basta elencarli separandoli con una virgola.
Esempio
5
SELECT
* FROM CLIENTI ORDER BY PROV
Questo comando SQL ordina per provincia e a parità di provincia ordina
per Ragione Sociale.
L’ordine dei campi nella clausola sql ORDER BY è
importante. Non è la stessa cosa scrivere
SELECT * FROM CLIENTI ORDER BY [Ragione Sociale],Prov
Se intendo fornire un elenco Clienti ordinato in maniera
decrescente per Ragione sociale
devo scrivere:
SELECT * FROM CLIENTI ORDER BY [Ragione Sociale] DESC
Il tag DESC, utilizzato nella clausola ORDER
BY, consente
l’inversione dell’ordinamento (decrescente).
Attenzione: se durante l'esecuzione di una query vi viene
chiesto di immettere un valore allora significa che il vostro comando
contiene il nome di un campo scritto in modo errato.
Il tag TOP n, utilizzato dopo la clausola SELECT, consente di visualizzare i record che occupano per primi la medesima posizione rispetto ad un determinato ordine. Se non è presente nella query la clausola ORDER BY allora mostra semplicemente i primi n record ! Vediamo un esempio:
SELECT top 1 [Ragione Sociale], Prov from clienti order by prov
produce questo risultato
poichè:
- "BG" è la prima
provincia (in ordine alfabetico) all'interno di Clienti
- i
clienti bergamaschi sono 3.
Se m è il numero di record visualizzati con TOP 1 allora TOP 2 ... TOP m produrranno sempre lo stesso elenco di record ovvero il comando SQL seguente:
SELECT top 3 [Ragione Sociale], Prov from clienti order by prov
produce ancora il risultato ottenuto con TOP 1:
Quando n supera m verranno aggiunti tutti i record che rispetto alla clausola di ordinamento occupano la stessa successiva posizione. Pertanto il comando:
SELECT top 4 [Ragione Sociale], Prov from clienti order by prov
restituisce questo output:
Ne consegue che TOP 4 ... TOP 7 producano sempre il medesimo risultato. Il ragionamento va applicato anche per i valori di n superiori. Ad esempio
SELECT top 8 [Ragione Sociale], Prov from clienti order by prov
restituisce questo output (idem anche TOP 9):
FILTRI |
Partiamo con un esempio:
SELECT
* FROM CLIENTI WHERE FATTURATO>100
Questa query estrae i clienti che hanno fatturato superiore
a 100 Euro.
La clausola WHERE serve per creare un filtro sulle righe da visualizzare. La clausola WHERE è seguita dalla condizione che stabilisce le regole di selezione delle righe nella tabella. Verranno visualizzate solo le righe per le quali la condizione risulta VERA.
SELECT * FROM CLIENTI WHERE TRUE
Esempio 6
SELECT * FROM CLIENTI WHERE (FATTURATO>100) AND (FATTURATO<500)
Nell'esempio verranno mostrati tutti i clienti il cui fatturato risulta compreso tra 100 e 500 euro (estremi esclusi).
L’ordine di valutazione delle
singole condizioni
collegate dall'AND o dall'OR non è importante ai fini del calcolo dell'intera
espressione condizionale
quindi:
(Fatturato<50) OR (Fatturato >150)
è equivalente a
(Fatturato>150) OR (Fatturato <50)
Esempio 7:
Attenzione
ad un uso corretto delle parentesi tonde. Infatti queste definiscono le
precedenze con cui vanno valutate le singole condizioni presenti nella
clausola WHERE.
Quindi
scrivere (esempio 7A)
SELECT * FROM CLIENTI WHERE ( (FATTURATO<100) OR (FATTURATO>500) ) AND (PROV=’BS’)
non è la stessa cosa di (esempio 7B)
SELECT * FROM CLIENTI WHERE (FATTURATO<100) OR ((FATTURATO>500) AND (PROV=’BS’))
Nel primo caso verranno visualizzati i clienti con fatturato non compreso tra 100 e 500 residenti a Brescia. Nel secondo caso invece verranno visualizzati i clienti con fatturato inferiore a 100 euro oppure quelli di Brescia con fatturato >500.
In
Access il singolo apice ' (usato nell'esempio 7 in corrispondenza
del campo
In OpenOffice Base per identificare le
costanti di tipo stringa si deve utilizzare obbligatoriamente il singolo apice
('). La scrittura
L'operatore booleano AND ha precedenza sull’OR (come lo * rispetto al + nelle operazioni algebriche) e pertanto l’interprete SQL risolve prima le condizioni legate dall'AND e successivamente le altre legate dall'OR.
Quindi
considerando l'esempio
SELECT * FROM CLIENTI WHERE (FATTURATO>100) AND (FATTURATO<500) OR (PROV=’BS’)
l'interprete SQL prima risolve
(FATTURATO>100) AND (FATTURATO<500)
e successivamente legherà il risultato con l'OR
(oppure) relativo alla provincia di Brescia.
L'uso delle parentesi può alterare la precedenza
dell'AND rispetto all'OR. Eccone un esempio.
SELECT
* FROM CLIENTI WHERE
(FATTURATO>100) AND
((FATTURATO<500) OR (PROV='BS'))
La condizione ((FATTURATO<500) OR (PROV='BS')) è
risolta per prima. Successivamente il risultato viene combinato con l'altra
condizione associata all'AND
In generale le condizioni usate nella clausola WHERE hanno
una sintassi del tipo:
Condizione1 <operatore1> Condizione2 <operatore2>
Esempio 9
SELECT
* FROM CLIENTI WHERE (DATAREG >= #05/27/2001#)
Questo esempio evidenzia la sintassi delle costanti di tipo
data. Una data in un comando SQL va racchiusa tra #. Si noti la
posizione del mese e del giorno che risultano invertite rispetto alla nostra
notazione (tipico della datazione anglosassone).
In OpenOffice Base per identificare le costanti di tipo data/ora occorre utilizzare una sintassi particolare visibile nell'esempio seguente:
SELECT * FROM Clienti WHERE DataReg >= {D '2001-05-27' }
La lettera
Esercizi:
1 - Costruire una query che consideri tutti i clienti di Brescia o di Bergamo e che hanno una data di registrazione compresa tra il 2 giugno e il 31 dicembre 2001SELECT
* FROM CLIENTI WHERE
((PROV='BS')
OR (PROV='BG') )
AND
( (DATAREG<=#12/31/2001#)
AND (DATAREG>=#06/02/2001#)
2 – Costruire la query
che mi elenchi le sole Ragioni Sociali della tabella Clienti ordinate per provincia
e con
fatturato maggiore di 150 euro oppure minore di 50
SELECT [Ragione Sociale] FROM CLIENTI WHERE (Fatturato<50) OR (Fatturato >150) ORDER BY PROV
Ricordatevi: le parentesi
vanno controllate soprattutto quando l'espressione booleana del WHERE contiene operatori AND e OR contemporaneamente.
3 – Costruire la query che elenchi i clienti che iniziano per la lettera A (
[ragione sociale] like 'A*') e con provincia uguale a BS o BGSELECT * FROM CLIENTI
WHERE ([Ragione Sociale] like
'A*') AND
(
(PROV='BS')
OR (PROV='BG')
)
RICERCHE CON L'OPERATORE LIKE |
LIKE è un operatore molto
simile all’uguale =
E’ utilizzato solo per campi
di tipo stringa (testo e memo). Consente la ricerca per sottostringhe (esempio
per controllare se una certa parola è presente in un certo campo).
Esempio 10:
Se voglio visualizzare tutti i clienti che iniziano per A posso scrivere:
SELECT
* FROM Clienti WHERE
([Ragione Sociale] LIKE
'A*')
In OpenOffice Base al posto di * si usa %.
L'operatore
SELECT * FROM Clienti WHERE "Ragione Sociale" LIKE 'A%'
estrae le aziende la cui Ragione Sociale inizia con la lettera A maiuscola.
Per rendere la ricerca case-insensitive si può
fare ricorso alla funzione
SELECT * FROM Clienti WHERE Lower("Ragione Sociale") LIKE 'a%'
SELECT * FROM Clienti WHERE UppER("Ragione Sociale") LIKE 'A%'
Esempio 11
Se voglio trovare tutti i Clienti la cui Ragione Sociale termina per 'SPA' (Società per azioni) posso scrivere:
SELECT
* FROM Clienti WHERE ([Ragione Sociale] LIKE
'*SPA')
Con questa clausola vengono
visualizzate le aziende con ragione sociale come: 'ROSSI SPA', 'Bianchi SpA'
Esempio 12:
Se intendo visualizzare i
clienti la cui ragione sociale contiene la parola CASA
SELECT
* FROM Clienti WHERE ([Ragione Sociale] LIKE
'*CASA*')
Attenzione nello standard SQL il carattere * è sostituito con il carattere %
Esempio
Immaginiamo di creare una query
di questo tipo e di salvarla:
SELECT
*
FROM
Clienti
WHERE ([Ragione Sociale] like [dammi la lettera iniziale] & "*");
Adesso il pannello Query contiene la query appena salvata. Proviamo ad aprirla.
Lanciandola (eseguendola)
ACCESS non trova alcun riferimento a
[dammi la lettera
iniziale]. Mediante la finestra di dialogo qui sopra
Access chiede all'utente di valorizzarla.
La scelta di una frase
opportuna racchiusa tra [] rende chiaro il significato di ciò che si vuol
ricevere come informazione dall'utente.
Al posto di
[dammi la lettera
iniziale] potevo utilizzare qualsiasi sequenza di
caratteri; ad esempio [Pluto]. Al momento dell'esecuzione della query la
richiesta di valorizzare [Pluto] lascia perplesso l'utente che non
intuisce
il significato del valore richiesto.
where "Ragione Sociale" like concat(:dammi_la_lettera_iniziale,'%')
Altra osservazione in merito a questo esempio è l'utilizzo dell'operatore & o di concatenazione di stringhe:
esempio:
"Ciao " & "Marco" diventa "Ciao Marco"
& corrisponde al + delle espressioni algebriche ma viene utilizzato per unire 2 stringhe in una sola.
Attenzione: l'& non è un operatore commutativo ovvero
'Ciao ' & 'Paola' è 'Ciao Paola'
'Paola' & 'Ciao ' è 'PaolaCiao '
Esempio 14:
Consideriamo una tabella
Alunni dove i campi Nome e Cognome risultano distinti. Se voglio creare una
query che li unisca posso procedere in questo modo
SELECT
(Cognome & ' ' & Nome)
AS Nominativo From ALUNNI
Lo ' ' (2 singoli apici separati da uno spazio) è usato per separare il Cognome dal Nome.
LA SINTASSI DEI COMANDI SELECT |
SELECT
[NOME
DEI CAMPI DA VISUALIZZARE SEPARATI DALLA
VIRGOLA]
FROM [ELENCO TABELLE DOVE
PRELEVO I DATI SEPARATE DALLA VIRGOLA]
WHERE [CONDIZIONI LEGATE DA AND ED OR]
ORDER BY [ELENCO DEI CAMPI DI
ORDINAMENTO SEPARATI DALLA VIRGOLA]
QUERY STATISTICHE O DI RAGGRUPPAMENTO |
Con questo tipo di query è possibile ottenere delle statistiche sulle tabelle. Ad esempio posso stabilire quanti libri sono stati prestati in un certo periodo, quanto è il fatturato di una azienda distinto per provincia etc. Iniziamo considerando quelle statistiche che riguardano la globalità dell'archivio. La sintassi per questo tipo di query di raggruppamento risulta semplificata ed esattamente:
SELECT Funzione(NomeCampo) AS NomeDaVisualizzare FROM NomeTabella
Dove Funzione è una particolare statistica. L'elenco completo di queste funzioni verrà dato successivamente:
Esempio 15:
SELECT
Count(*) AS NumeroClienti
Questa query utilizza la funzione Count
che effettua un conteggio. Il risultato è il
numero di clienti presenti nella tabella
Esempio 16:
SELECT Max(Fatturato) AS MassimoFatturato
FROM CLIENTI
Questa query fornisce il
massimo fatturato realizzato.
Esempio 17:
SELECT
Min(DataReg) AS PrimaRegistrazione
FROM CLIENTI
Restituisce la data della prima registrazione.
Esempio 18:
SELECT Avg(Fatturato) AS FatturatoMedio
FROM CLIENTI
Calcola il fatturato medio
globale
Esempio 19:
SELECT Sum(Fatturato) AS TotaleIncassato FROM CLIENTI
Calcola il fatturato totale
dell’azienda.
Le Query viste si basano su particolari funzioni statistiche ed esattamente:
n
SUM(NomeCampo) à
Somma dei valori contenuti in NomeCampo
n
AVG(NomeCampo) à
Media (average) dei valori contenuti in NomeCampo
- VAR(NomeCampo) che restituisce la varianza
- STDEV(NomeCampo) che restituisce la deviazione
standard corretta.
Per approfondire l'argomento relativo alla deviazione standard clicca
qui.
n
MAX(NomeCampo) à
Valore massimo contenuto in NomeCampo
n
MIN(NomeCampo) à
Valore minimo contenuto in NomeCampo
n COUNT(*) o COUNT(NomeCampo) à Conteggia il numero di schede che sono presenti in una tabella. Usando la clausola WHERE calcolo il numero di record che soddisfano una certa condizione. Si noti che mettere * o un nome di un campo come argomento nella funzione COUNT è la stessa cosa.
n
FIRST(NomeCampo) à
Visualizza il valore contenuto in NomeCampo della 1^ scheda registrata della tabella
n
LAST(NomeCampo) à
Visualizza il valore contenuto nell’ultima scheda della tabella nel campo
NomeCampo
In
alcuni casi le statistiche non riguardano la globalità della tabella ma si
riferiscono ai valori possibili contenuti in un singolo campo: si pensi ad
esempio ad un elenco che visualizzi il numero di abitanti per regione.
Un altro esempio è fornire il
numero di studenti per classe partendo da una tabella contenente
l’elenco di tutti gli alunni iscritti in un istituto scolastico. (è
sostanzialmente una statististica rispetto a qualche raggruppamento).
Per questo tipo di
statistiche la costruzione del comando SQL segue questa sintassi:
SELECT
NomeCampoRaggruppato, Funzione(NomeCampoRaggruppato)
FROM
NomeTabella
[WHERE
Condizione1 operatoreLogico1 ...]
GROUP BY NomeCampoRaggruppato
[ORDER BY NomeCampoRaggruppato]
[HAVING
CondizioneSuFunzioneRaggruppamento
operatoreLogicoA ...
]
Esempio 20:
Se voglio conoscere il numero
di clienti per provincia posso scrivere:
SELECT
Provincia, Count(*) AS Numero
FROM Clienti GROUP BY Provincia
Il risultato ottenuto eseguendo questa query è:
Esempio 21:
Si consideri la seguente
tabella studenti:
Posso contare il numero di studenti per classe
con questa query:
SELECT Classe, Count(*) AS [Numero studenti]
FROM Studenti
GROUP BY Classe
ORDER BY Classe
che
eseguita restituisce questo
risultato
Se voglio visualizzare il numero di studenti
di
ogni classe
del quarto anno devo modificare la query in questo modo:
SELECT Classe, Count(*) AS [Numero studenti]
FROM Studenti
WHERE Classe like "4*"
GROUP BY Classe
ORDER BY Classe
La sua esecuzione mostra questo risultato
Se invece desidero elencare le classi che hanno più di 28 alunni devo impostare la seguente query:
SELECT Classe, Count(*) AS [Numero studenti]
FROM Studenti
GROUP BY Classe
HAVING (Count(*)>28)
ORDER BY Classe;
che genera il seguente elenco
Infine se voglio elencare le classi della sezione "T" che hanno più di 28 alunni devo scrivere questa query:
SELECT Classe, Count(*) AS [Numero studenti]
FROM Studenti
WHERE Classe like "*T"
GROUP BY Classe
HAVING (Count(*)>28)
ORDER BY Classe;
che eseguita produce questo elenco
In merito alle direttive
Where ed Having è necessario ora fare delle precisazioni per illustrare quando vanno utilizzate.Partiamo dalla seguente query che fornisce il medesimo risultato della query precedente ma non è corretta ed inoltre risulta più lenta
SELECT Classe, Count(*) AS [Numero studenti]
FROM Studenti
GROUP BY Classe
HAVING (Count(*)>28)
AND Classe like "*T"
ORDER BY Classe;
Gestendo il filtro sulle classi della sezione "T" mediante la direttiva Having costringo il database ad applicare il
Group By sull'intero archivio B=A.
Poichè l'operazione di raggruppamento rappresenta l'operazione più pesante in termini computazionali ne consegue un aumento dei tempi di risposta dovuto al maggior numero di record B da analizzare. Il filtro gestito dalla direttiva Having si limita a mostrare/nascondere i risultati C della statistica producendo un risultato finale D che non incide mai in modo sensibile sui tempi di esecuzione complessivi.
Se invece utilizzo la query corretta:
SELECT Classe, Count(*) AS [Numero studenti]
FROM Studenti
WHERE Classe like "*T"
GROUP BY Classe
HAVING (Count(*)>28)
ORDER BY Classe;
la direttiva Where effettua una selezione dell'insieme originale dei record A restituendo solitamente un insieme numericamente inferiore B composta da quei record che soddisfano la condizione α.
Questo filtro riduce i dati su cui viene applicata l'operazione di raggruppamento e quindi il risultato intermedio C può essere prodotto in un tempo inferiore rispetto a quello necessario per raggruppare l'intero insieme dei record A. La direttiva Having, come già citato in precedenza, si limita a filtrare i risultati del Group By C mostrando solo le righe D che soddisfano la condizione β: il tutto senza incidere in modo significativo sui tempi di esecuzione complessivi.
Quindi per garantire massime performance è preferibile applicare subito tutti i filtri richiesti (tramite la direttiva Where) al fine di diminuire la quantità di record su cui applicare il Group By riducendo il carico di lavoro associato all'operazione di raggruppamento che rappresenta la componente computazionale che incide maggiormente sui tempi di esecuzione complessivi della query.
I filtri sulle funzioni statistiche (calcolate dopo il Group By) devono essere obbligatoriamente applicati solo dopo l'operazione di raggruppamento e pertanto non possono essere applicati sull'insieme originale dei record A (clausola Where) ma solo sul risultato del Group By C quindi tramite la clausola Having.
Riassumendo nelle query di raggruppamento i filtri sulle funzioni statistiche devono essere gestiti con la direttiva Having mentre tutti gli altri casi devono essere trattati con la clausola Where.