Sei sulla pagina 1di 60

SQL

R.Bellazzi, S.Quaglini, G. Lanzola Dipartimento di Informatica e Sistemistica, Universit di Pavia

SQL (Structured Query Language)


Linguaggio per la definizione, manipolazione, ed il controllo dei dati in un data-base relazionale Adottato ufficialmente come standard da ANSI, ISO Utilizzato dai principali pacchetti per la gestione di basi di dati, come Oracle, Informix, Sybase e, per applicazioni home made, Access

Cenni storici
Modello relazionale introdotto nei laboratori IBM negli anni 70 Linguaggi per basi di dati relazionali: SEQUEL, SEQUEL/2 ed infine SQL Immediatamente adottato come standard de facto Esistono vari dialetti, che hanno un kernel condiviso

Propriet di SQL
Istruzioni per la definizione, manipolazione, controllo di un Database relazionale Istruzioni visualizzabili in modo interattivo Chiamate allinterno di un host language in cui viene realizzata lapplicazione (embedded SQL) come in PL-SQL Utilizzate allinterno di tools grafici basati su Forms (Access)

Propriet di SQL - 2
SQL manipola database relazionali La base di dati quindi costituita da Tabelle Le procedure SQL manipolano delle Tabelle e consentono di interrogare la base dati,

estraendo altre tabelle o creandone di nuove Le istruzioni di SQL permettono di operare su


un insieme di dati per volta e non su un singolo record SQL un linguaggio dichiarativo: lutente specifica cosa fare ma non come deve essere fatto

La base di dati di esempio


Sintesi dei ricoveri effettuati da un certo centro ospedaliero Analisi delle prestazioni effettuate e dei relativi costi Informazioni aggiuntive legate al centro

Diagnosi ricovero Codice Descrizione Dipendenti Codice_fisc Codice_dip Reparto Assunzione Dimissione Anzianit Codice_prof

DRG Codice Descrizione Rimborso

Interventi Cf_paziente Data Cod_ric Cf_med

Visite CF_Paziente Data Temp Pmax Presc CF_Med Reparti Codice Nome

Generale Codice_fisc Cognome Nome Nascita Sesso Citt Provincia

Prescrizioni Codice Nome Costo

Professioni Codice Descrizione Retribuzione_base

Ricoveri Codice_fisc Codice_prof Reparto Data_ingresso Data_uscita Diagnosi_ricovero DRG CF_medico

Diagnosi ricovero Codice Descrizione Dipendenti Codice_fisc Codice_dip Reparto Assunzione Dimissione Anzianit Codice_prof

DRG Codice Descrizione Rimborso

Interventi Cf_paziente Data Cod_ric Cf_med

Visite CF_Paziente Data Temp Pmax Presc CF_Med Reparti Codice Nome

Generale Codice_fisc Cognome Nome Nascita Sesso Citt Provincia

Prescrizioni Codice Nome Costo

Professioni Codice Descrizione Retribuzione_base

Ricoveri Codice_fisc Codice_prof Reparto Data_ingresso Data_uscita Diagnosi_ricovero DRG CF_medico

Troviamo le chiavi esterne


Generale
Cognome Nome Nascita Sesso Citt Provincia Ricoveri Chiave esterna

Codice_fisc

Codice_fisc

Codice_prof Reparto

Reparti Codice Nome

Data_ingresso

Data_uscita Diagnosi_ricovero DRG CF_medico Tabella dei ricoveri

Anagrafica del paziente

Diagnosi ricovero Codice Descrizione Dipendenti Codice_fisc Codice_dip Reparto Assunzione Dimissione Anzianit Codice_prof

DRG Codice Descrizione Rimborso

Interventi Cf_paziente Data Cod_ric Cf_med

Visite CF_Paziente Data Temp Pmax Presc CF_Med Reparti Codice Nome

Generale Codice_fisc Cognome Nome Nascita Sesso Citt Provincia

Prescrizioni Codice Nome Costo

Professioni Codice Descrizione Retribuzione_base

Ricoveri Codice_fisc Codice_prof Reparto Data_ingresso Data_uscita Diagnosi_ricovero DRG CF_medico

SQL e Tabelle - 1
SQL interagisce solamente con Tabelle Ad ogni intestazione di colonna associato un particolare tipo di dato e ciascuna linea contiene un valore per ogni colonna Non esiste la possibilit di inserire una tupla in un particolare ordine Le colonne si considerano ordinate allatto della creazione della tabella stessa Il nome della colonna unico: la chiave primaria del DBMS sempre user_name, table_name, column_name

SQL e Tabelle - 2
In SQL esistono tre tipi di Tabelle

Base: memorizzate nella base di dati Viste: tabelle virtuali, definite attraverso delle interrogazioni queries su altre tabelle Tabelle senza nome: tabelle restituite in seguito alla valutazione di una qualsiasi query

Creazione ed eliminazione di Tabelle


CREATE TABLE nome-tabella (nome-colonna1 tipo [NOT NULL], nome-colonna2 tipo [NOT NULL], ) crea Nome-tabella e nome-colonna devono iniziare con una lettera e non devono superare 18 caratteri I tipi di dati in SQL sono

DATE INTEGER SMALLINT (da 32767 a 32767) FLOAT Char(n): stringa di n caratteri (da 0 a 255) Varchar(n): stringa di n caratteri (da 0 a 255 o 2048 a seconda della versione)

DROP TABLE nome-tabella

elimina

Esercizio
Creare ed eliminare una Tabella nel data-base di esempio. Tabella da creare: Nome: Ospedale Attributi: Citt, ASL,Posti Letto, Data_Apertura ASL e posti letto non possono essere nulli

Modificare le colonne
ALTER TABLE nome-tabella ADD nomecolonna tipo AGGIUNGE COLONNA Esercizio:

Si ricrei la Tabella Ospedale e si aggiunga un attributo Direttore_sanitario, di tipo varchar(10)

ALTER TABLE nome-tabella MODIFY nomecolonna nuovo-tipo (non disponibile in SQL per Access)
MODIFICA TIPO

Inserimento dati nelle tabelle


INSERT INTO nome-tabella (nomecolonna1, nome-colonna2, ) VALUES (valore1, valore2, ) Forma 1 ESERCIZIO: Inserire due tuple nella relazione Ospedale INSERT INTO nome-tabella (nomecolonna1, nome-colonna2, ) VALUES espressione-select Forma 2

Note sullinserimento dati


Non indispensabile indicare il nome delle colonne; se esse non vengono specificate, SQL assume che si mantenga lordine di creazione della Tabella Se si specificano le colonne, si possono mettere in qualunque ordine Se mancano colonne, SQL introduce dei NULL ATTENZIONE: bisogna inserire dati compatibili con il tipo dati delle colonne

Le QUERY
Interrogazione dei dati in un database Espressioni di maggiore importanza in SQL Le query vengono realizzate grazie allistruzione SELECT Il risultato di questa istruzione sempre una tabella

Sintassi dellistruzione SELECT


SELECT {DISTINCT,ALL} [* | selezionecolonna] FROM identificatore-tabella {WHERE condizione} {GROUP BY nome-colonna} {HAVING condizione-having} {ORDER-BY ordine} Le parentesi graffe indicano parti opzionali della query

SELECT
Sei clausole al massimo SELECT e FROM obbligatorie Lordine delle clausole fisso Di norma la clausola HAVING si utilizza solo se presente la GROUP-BY

Esercizio: trovare le SELECT corrette


SELECT FROM ORDER BY SELECT WHERE ORDER BY SELECT FROM HAVING SELECT FROM GROUP BY HAVING SELECT WHERE ORDER BY SELECT WHERE FROM SELECT FROM WHERE SELECT ORDER BY FROM GROUP BY

Esempi (ed esercizi) semplici


SELECT provincia FROM GENERALE

Restituisce una Tabella di una colonna dove sono riportati le province

SELECT DISTINCT provincia FROM GENERALE

Restituisce una Tabella di una colonna dove sono riportati le province senza duplicati

SELECT nome,cognome,citta,provincia FROM GENERALE

Restituisce una Tabella con molte colonne (nb: ci sono anche campi vuoti)

Altri esempi
SELECT codice,descrizione,rimborso FROM DRG equivale a SELECT * FROM DRG

Lasterisco indica tutte le colonne

Una curiosit: trovare cosa restituisce


SELECT * FROM PROFESSIONI,DRG

Nota bene
SQL permette di fare elaborazioni sui dati:
SELECT drg.*,round(rimborso/1936.27) AS 'EURO' FROM drg ; drg.* specifica tutte le colonne di una data tabella AS permette di (ri)nominare la colonna Composizione di colonne diverse da quelle originali utilizzando costanti, operazioni e funzioni SQL

La clausola WHERE
SELECT nome,cognome,nascita FROM generale WHERE provincia=PV;

Effettuo un filtraggio dei dati

SELECT nome,cognome,nascita FROM generale WHERE provincia=PV AND sesso=F;

Effettuo un filtraggio dei dati mediante luso di operatori logici

La clausola ORDER BY
Consente di ordinare i record presentati nella tabella dei risultati secondo un ordinamento multi-livello SELECT descrizione,rimborso FROM DRG ORDER BY RIMBORSO SELECT descrizione,rimborso FROM DRG ORDER BY RIMBORSO ASC SELECT descrizione,rimborso FROM DRG ORDER BY RIMBORSO DESC

ORDER BY e WHERE
SELECT nome,cognome,nascita FROM GENERALE WHERE sesso=M AND provincia=PV ORDER BY COGNOME,NOME DESC SELECT reparto, data_ingresso, DRG FROM RICOVERI WHERE DATA_USCITA<#01/01/1980# order by codice_prof;

Un esempio con tutte le clausole


SELECT provincia FROM generale where sesso=F and nascita>#01/01/1960# GROUP BY provincia HAVING COUNT(*)>1 ORDER BY provincia

ORDINE DI ELABORAZIONE DELLE CLAUSOLE IN UNA SELECT


FROM: definisce la tabella cui accedere per lestrazione dei dati WHERE: seleziona le righe che soddisfano Una condizione

GROUP BY: raggruppa le righe in base ai valori uguali delle colonne specificate
HAVING: seleziona gruppi di righe che soddisfano una condizione SELECT: seleziona le colonne ORDER BY: ordina le righe secondo le colonne specificate

Ordine di elaborazione
FROM seleziona la tabella GENERALE del data-base WHERE seleziona le righe che corrispondono alla condizione sul sesso e sulla data di nascita
CODICE_FISC COGNOME NOME NASCITA SESSO CITTA PROVINCIA

ADJPSJASGHAKS147 ADJPSJASGHAKS180 ADJPSJASGHAKS181


ADJPSJASGHAKS218 ADJPSJASGHAKS257 ADJPSJASGHAKS266 DFDKE309ASLDKL09 DFKLJF3409WDKL09 DSKSD0934JKSDJKF KJIOESDSJKD94900 SAKJH3489SDJK89J SDJK389SDJK3RW89 SDL3RPDLDHJSD093 SDLDKLJKFD9SD9JK

Monti Vassallo De Luca


Alessi Gianotti Fantozzi Nostrile Baita Tamborra Corsetti Cerri Ferrario Rigamonti Gentile

Laura Ada Francesca


Franca Maria Maria Cristina Sabina Anna Franca Antonia Maria Carla Lucia

14/09/1964 03/11/1963 27/04/1964


16/01/1963 11/06/1960 03/12/1960 09/12/1961 12/03/1990 12/03/1989 09/11/1971 12/06/1982 26/12/1983 14/02/1983 28/12/1991

F F F
F F F F F F F F F F F

Copiano Milano Certosa


Broni Casteggio Pavia

PV MI PV
PV PV PV MI

Como Rho Bressana Roma Napoli Bressana Milano

CO MI PV RM NA PV MI

GROUP BY
La group by raggruppa le righe in base ai valori della colonna provincia
CODICE_FISC DFKLJF3409WDKL09 SDLDKLJKFD9SD9JK DSKSD0934JKSDJKF DFDKE309ASLDKL09 ADJPSJASGHAKS180 SDJK389SDJK3RW89 SDL3RPDLDHJSD093 KJIOESDSJKD94900 ADJPSJASGHAKS266 ADJPSJASGHAKS257 ADJPSJASGHAKS218 ADJPSJASGHAKS181 ADJPSJASGHAKS147 SAKJH3489SDJK89J COGNOME Baita Gentile Tamborra Nostrile Vassallo Ferrario Rigamonti Corsetti Fantozzi Gianotti Alessi De Luca Monti Cerri NOME Sabina Lucia Anna Cristina Ada Maria Carla Franca Maria Maria Franca Francesca Laura Antonia NASCITA 12/03/1990 28/12/1991 12/03/1989 09/12/1961 03/11/1963 26/12/1983 14/02/1983 09/11/1971 03/12/1960 11/06/1960 16/01/1963 27/04/1964 14/09/1964 12/06/1982 SESSO F F F CITTA Como Milano Rho PROVINCIA CO MI

F
F F F F F F F F F F Milano Napoli Bressana Bressana Pavia Casteggio Broni Certosa Copiano Roma RM NA PV

HAVING
E simile alla where, ma agisce sui gruppi. Nellesempio seleziona tutti i gruppi con un numero di elementi maggiore di uno (count(*))
CODICE_FISC DFKLJF3409WDKL09 SDLDKLJKFD9SD9JK DSKSD0934JKSDJKF DFDKE309ASLDKL09 ADJPSJASGHAKS180 SDL3RPDLDHJSD093 KJIOESDSJKD94900 ADJPSJASGHAKS266 ADJPSJASGHAKS257 ADJPSJASGHAKS218 ADJPSJASGHAKS181 ADJPSJASGHAKS147 COGNOME Baita Gentile Tamborra Nostrile Vassallo Rigamonti Corsetti Fantozzi Gianotti Alessi De Luca Monti NOME Sabina Lucia Anna Cristina Ada Carla Franca Maria Maria Franca Francesca Laura NASCITA 12/03/1990 28/12/1991 12/03/1989 09/12/1961 03/11/1963 14/02/1983 09/11/1971 03/12/1960 11/06/1960 16/01/1963 27/04/1964 14/09/1964 SESSO F F CITTA Como Milano Rho PROVINCIA CO MI

F
F F F F

Milano Bressana Bressana Pavia Casteggio Broni Certosa Copiano PV

F
F F F F

SELECT e ORDER BY
Seleziona le colonne. La SELECT in questo caso pu selezionare soltanto le colonne con il medesimo valore per ogni gruppo, o su cui si siano effettuate delle funzioni di aggregazione. Nel nostro caso vengono selezionate le province La ORDER BY ordina i risultati in ordine alfabetico
provincia MI PV

Se avessimo voluto recuperare anche la colonna della data di nascita, avremmo dovuto introdurre nella SELECT un operatore di aggregazione, ad es. max: (select max(data_di_nascita )
max_nasc 28/12/1991 14/02/1983 provincia MI PV

Note sulla FROM


Se nella FROM menzionata una sola tabella, questa quella che verr restituita Altrimenti restituisce una nuova tabella con il prodotto cartesiano fra le righe di tutte le colonne menzionate SELECT * FROM DRG d,REPARTI r;

Gruppi
La clausola GROUP BY raggruppa le righe della tabella derivata dallapplicazione delle clausole FROM e WHERE suddividendole in base ai valori della colonna specificata Ovviamente i gruppi possono avere colonne con pi di un valore La colonna di raggruppamento, viceversa, avr pi di un valore La clausola HAVING equivalente alla WHERE ma agisce solo sui dati raggruppati Nella SELECT possono solo comparire funzioni di aggregazione e/o colonne presenti nella GROUP BY

Join
Si ha una JOIN fra tabelle quando nella clausola FROM viene referenziata pi di una tabella, e nella clausola WHERE presente una condizione che confronta tabelle diverse. Esempio: quale il nome e cognome dei dipendenti dellospedale? Soluzione: SELECT DISTINCT generale.nome, generale.cognome, dipendenti.codice_prof FROM generale,dipendenti WHERE dipendenti.codice_fisc=generale.codice_fisc

Note sulla JOIN


E spesso indispensabile utilizzare un riferimento ai nomi delle colonne del tipo fully qualified: nome_tabella.nome_attributo Si possono inoltre utilizzare dei nomi interni (detti range variables) per denotare delle colonne Luso delle range variables indispensabile quando si debbano usare le stesse colonne della stessa tabella pi volte

Esercizio
Trovare il nome ed il cognome dei primari dellospedale nei diversi reparti Soluzione
SELECT generale.nome,generale.cognome,reparti.nome,professioni .descrizione FROM generale,dipendenti, reparti, professioni WHERE professioni.descrizione='primario and dipendenti.codice_prof=professioni.codice and dipendenti.codice_fisc=generale.codice_fisc and dipendenti.reparto=reparti.codice

Diagnosi ricovero Codice Descrizione Dipendenti Codice_fisc Codice_dip Reparto Assunzione Dimissione Anzianit Codice_prof

DRG Codice Descrizione Rimborso

Interventi Cf_paziente Data Cod_ric Cf_med

Visite CF_Paziente Data Temp Pmax Presc CF_Med Reparti Codice Nome

Generale Codice_fisc Cognome Nome Nascita Sesso Citt Provincia

Prescrizioni Codice Nome Costo

Professioni Codice Descrizione Retribuzione_base

Ricoveri Codice_fisc Codice_prof Reparto Data_ingresso Data_uscita Diagnosi_ricovero DRG CF_medico

Join e subqueries
Esempio: trovare gli elementi della tabella di anagrafica fra loro coetanei Non posso usare listruzione GROUP BY: non riesco a farmi restituire i nomi dei soggetti Select nascita, count(*) from generale group by nascita having count(*)>2

Soluzioni
Join della tabella con se stessa
SELECT DISTINCT gen1.nome, gen1.cognome, gen1.nascita FROM generale gen1, generale gen2 where gen1.nascita=gen2.nascita and gen1.codice_fisc<>gen2.codice_fisc order by gen1.nascita

Query annidate
SELECT gen1.nome, gen1.cognome, gen1.nascita FROM generale gen1 where gen1.nascita in (select gen2.nascita from generale gen2 group by gen2.nascita having count(nascita)>=2) order by gen1.nascita

Non esiste un limite di annidamento, anche se 3 un buon numero magico

Operatori disponibili con la clausola WHERE - I


La clausola where considera il test logico ad essa associata soddisfatto quando true Ci possono essere dei valori nulli che inficiano il test (o meglio ne variano tabelle della verit) Ricordare che NULL un nuovo valore di verit tale che T and NULL=NULL e F and NULL=F, T or NULL=T, F or NULL=NULL I null sono considerati uguali nella select distinct e nelle direttive di ordinamento e raggruppamento I valori nulli possono essere trovati nelle where mediante la condizione IS NULL: E.g: SELECT cognome nome from generale where nascita is null

Gli operatori disponibili nella WHERE -II


BETWEEN:
b <= a <= c

A BETWEEN B AND C ha il significato

SELECT nome, cognome, nascita from generale where nascita between #01/01/1960# AND #01/01/1964#

LIKE: simile alluguaglianza di stringhe ma pi generale

SELECT nome, cognome, nascita from generale where citta like B* cerca tutte le citt che iniziano con la lettera B SELECT nome, cognome, provincia from generale where provincia in ('AL','LO') order by provincia

IN: cerca in un elenco (una select o una lista)

Gli operatori disponibili nella WHERE -III


ALL/ANY esercizio: troviamo la persona assunta pi di recente in ospedale Soluzione SELECT g.nome, g.cognome, d.assunzione FROM generale g,dipendenti d WHERE g.codice_fisc=d.codice_fisc and d.assunzione >= all (select assunzione from dipendenti) ANY viceversa soddisfatto quando almeno un elemento della lista (select) verifica la condizione

Gli operatori disponibili nella WHERE -IV


EXISTS: restituisce FALSE se la lista vuota TRUE altrimenti Esempio di utilizzo: si trovino i DRG non impiegati nella tabella ricoveri
select descrizione from drg where not exists (select distinct drg from ricoveri where drg.codice=ricoveri.drg)

Esempio di subquery correlata: si referenziano delle colonne che sono state introdotte nella query precedente

Accorgimenti sulle subquery


Una subquery deve essere sempre racchiusa fra una coppia di parentesi Ciascuna subquery deve restituire una tabella dotata di una sola colonna compatibile con listruzione Tutte le colonne devono essere ben specificate (colonne fully qualified)

Esercizi
Nome dei pazienti ricoverati nel reparto di medicina interna
select g.nome,g.cognome from generale g, ricoveri r where g.codice_fisc = r.codice_fisc and reparto in (select reparti.codice from reparti where reparti.nome='Medicina Interna') order by g.cognome

Esercizi
Nome dei primari dei vari reparti
select distinct g.nome,g.cognome,r.nome from generale g, dipendenti d, reparti r where g.codice_fisc = d.codice_fisc and d.reparto=r.codice and d.codice_prof in (select professioni.codice from professioni where professioni.descrizione='Primario') order by g.cognome

Funzioni di aggregazione
COUNT(*): restituisce il numero di record presenti nellaggregato COUNT(), MIN(), MAX() possono essere utilizzati su tutti i campi SUM e AVG si possono utilizzare su campi numerici Esempio: la data di nascita pi recente nella tabella di anagrafica Select max(nascita) from generale

Esercizio
Si trovi il minimo, il massimo, il totale e la media degli stipendi percepiti ed il numero di dipendenti in ogni classe stipendiale NB: la retribuzione calcolata come anzianit * retribuzione base /100
SELECT p.DESCRIZIONE, Min(p.retrib_base*anzianita/100) AS minimo, Max(p.retrib_base*anzianita/100) AS massimo, Avg(p.retrib_base*d.anzianita/100) AS media, Count(*) AS numero FROM dipendenti AS d, professioni AS p WHERE (((d.CODICE_PROF)=[p].[codice])) GROUP BY p.DESCRIZIONE, p.CODICE;

Altri comandi SQL


INSERT consente di inserire in una colonna anche il risultato di una precedente select, a patto di avere le stesse dimensioni nelle tabelle SELECT colonne INTO tab2 from tab1 crea una nuova tabella con il contenuto della query UPDATE consente di modificare i valori dei campi di record gi esistenti DELETE permette di cancellare un numero arbitrario di tuple dalla tabella

UPDATE e DELETE
Creiamo una tabella di prova
SELECT * into temp from professioni

Sostituiamo le lire con gli Euro update temp set retrib_base=retrib_base/1936.27 where retrib_base is not null Togliamo le righe nulle delete from temp where retrib_base is null

UNION
Mediante UNION si possono specificare pi tabelle in un unico risultato Le tabelle sorgenti devono avere lo stesso numero di colonne e lo stesso tipo dei dati SELECT nome,costo from prescrizioni UNION SELECT descrizione,rimborso from drg; In assenza della direttiva ALL vengono rimossi i duplicati

VISTE
Tabelle virtuali. Il loro contenuto ricavato da altre tabelle mediante una query Viene memorizzata la struttura della query e rieseguita ogni volta In ACCESS le query salvate possono essere considerate delle viste Si possono effettuare delle query su viste In altri DBMS esiste il comando CREATE VIEW che permette di effettuare la medesima operazione

Esercizi
1. Si trovi qual il numero totale dei suoi
ricoveri e in quali e quanti reparti stato ricoverato ciascun paziente 2. Si trovino i reparti che hanno ricoverato pi persone 3. Si inserisca una nuova professione nella tabella delle professioni senza sapere lultimo numero assegnato 4. Si trovi chi viene pagato pi della media di categoria

Esercizio
Si trovi nome, cognome, reparto del pi anziano dipendente dellospedale select g.nome, g.cognome, g.nascita, rep.nome,d.codice_dip from generale g, dipendenti d, reparti rep where nascita in (SELECT min(nascita) from generale as g, dipendenti as d where g.codice_fisc=d.codice_fisc) and g.codice_fisc=d.codice_fisc and rep.codice=d.reparto

Esercizio 1
SELECT nome, cognome, count(*) as numero FROM ricoveri r, generale g WHERE g.codice_fisc=r.codice_fisc GROUP BY r.codice_fisc, nome, cognome SELECT distinct g.nome,g.cognome, g.codice_fisc, rep.nome into test1 FROM ricoveri as r, generale as g, reparti as rep WHERE r.codice_fisc=g.codice_fisc and rep.codice=r.reparto ORDER BY cognome; SELECT t.nome, t.cognome, count(*) as numero_reparti FROM test1 as t GROUP BY t.codice_fisc t.cognome, t.nome;

Esercizio 2
SELECT reparti.nome, count(*) AS numero_ricoveri from ricoveri,reparti where codice=reparto group by reparto, reparti.nome having count(*)>1

Esercizio 3
INSERT into professioni select max(codice_prof)+1, Nuova from professioni

Esercizio 4
SELECT nome,cognome, p.descrizione, (p.retrib_base*d.anzianita/100) as retribuzione, (SELECT Avg(p1.retrib_base*d1.anzianita/100) FROM dipendenti d1, professioni as p1 WHERE d1.codice_prof=p.codice and d1.CODICE_PROF=d.codice_prof) as media FROM generale g, professioni p, dipendenti d WHERE d.codice_prof=p.codice and d.codice_fisc=g.codice_fisc and (p.retrib_base*d.anzianita/100) > (SELECT Avg(p1.retrib_base*d1.anzianita/100) FROM dipendenti d1, professioni as p1 WHERE d1.codice_prof=p1.codice and d1.CODICE_PROF=d.codice_prof);

Potrebbero piacerti anche