Welcome to Oracle
Ho finalmente finito di scrivere il manuale Oracle “Welcome to Oracle” disponibile gratuitamente su questo sito sotto licenza Commons Creative (tutti i dettagli nella “nota sul diritto d’autore” all’interno del libro).
Il manuale si rivolge sia ai principianti che agli utilizzatori di Oracle già esperti.
Scaricatelo e leggetelo, ogni segnalazione d’errore o possibile miglioria è ben accetta!
Se poi dovesse piacervi così tanto da desiderarne una copia cartacea è possibile acquistarlo

Se il libro vi è stato utile e concordate con quello che ho scritto nella “Nota sul diritto d’autore”, siete liberi di effettuare una donazione a piacere utilizzando paypal:
Per scaricare il libro utilizzare questo link: Welcome to Oracle.pdf
Per utilizzare gli esempi del manuale “Welcome to Oracle” è necessario creare il database di esempio.
Dopo avere installato il db come indicato nel manuale, è possibile creare lo schema WTO_ESEMPIO lanciando da SQL*Plus (connessi con l’utente system) lo script WTO ESEMPIO e popolare tutte le tabelle lanciando lo script WTO INSERT


6 giugno 2011 alle 09:50 |
Accidenti, è un librone di 566 pagine! Lo leggerò senz’altro, non capita tutti i giorni di leggere materiale Oracle concepito in lingua italiana (le traduzioni le evito, sono sempre piene di errori).
Grazie,
Roberto
6 giugno 2011 alle 10:34 |
Però c’è parecchio codice SQL e PL/SQL, quindi le chiacchiere non sono troppe!
D’altronde più di così non sono riuscito a sintetizzare…
Grazie,
Massimo
6 giugno 2011 alle 10:17 |
Ciao Massimo, l’ho scaricato nel mio tablet, appena ho un attimo mi impegnerò a leggerlo. grazie 1000.
Ciao
Alberto
6 giugno 2011 alle 10:32 |
Perfetto, così mi fai sapere pure com’è la leggibilità su tablet! Grazie a te.
Massimo
8 giugno 2011 alle 16:36 |
Ciao Massimo,
ho cominciato a leggerlo e devo dire che la leggibilità nel mio tablet è ottima, inoltre anche le argomentazioni trattate nel libro sono ottime, spaziano dai concetti base ad esempio concreti. Mi sono letto la parte relativa alla programmazione PL/SQL e più precisamente relativa ai cursori, questo perchè è un pò di tempo che mi tengo informato sull’ottimizzione di questi nelle performance di un DB, (tra l’altro postate nel mio blog) visto che tutto parte da una buona programmazione.
Ottimo lavoro ci avrai dedicato tanto tempo nel riscrivere tutto.
Materiali che trattano Oracle in italiano purtroppo sono rari.
continuo nella lettura e ancora complimenti.
Ciao
Alberto
10 giugno 2011 alle 16:17 |
Massimo, mi autonomino revisore (o uno dei revisori se si fa avanti qualcun altro) del tuo libro. Per ora ho letto i primi 4 capitoli, più il decimo di introduzione. Conto nel tempo, in maniera discontinua, di leggere tutto.
Come posso farti pervenire le mie “correzioni”?
10 giugno 2011 alle 16:52 |
poi scrivere a welcome.to.oracle@gmail.com
grazie mille!
Massimo
13 luglio 2011 alle 19:13 |
Ad ogni log switch viene eseguito sempre un checkpoint!!!
Ma chi te le ha insegnata questa cosa!!!
come mai, allora, dopo un log switch il redo log che prima era current diventa active e nn può essere cancellato???
E che differnza c’è con un redo inactive???
ho dato un’occhiata a questo libro trovando tante inesattezze …
Conosci il pl/sql ma nn sei un dba…
nn conosci come funziona oracle…
14 luglio 2011 alle 00:45 |
Per fortuna il mio libro è gratis, quindi puoi cancellarlo e non ti è costato nulla…
Però una cosa almeno l’hai imparata:
Oracle Database Concepts http://download.oracle.com/docs/cd/E11882_01/server.112/e16508/startup.htm#CNCPT89045
When Oracle Database Initiates Checkpoints
The checkpoint process (CKPT) is responsible for writing checkpoints to the data file headers and control file. Checkpoints occur in a variety of situations. For example, Oracle Database uses the following types of checkpoints:
•Thread checkpoints
The database writes to disk all buffers modified by redo in a specific thread before a certain target. The set of thread checkpoints on all instances in a database is a database checkpoint. Thread checkpoints occur in the following situations:
◦Consistent database shutdown
◦ALTER SYSTEM CHECKPOINT statement
◦Online redo log switch
◦ALTER DATABASE BEGIN BACKUP statement
Ciao,
Massimo
18 luglio 2011 alle 10:25 |
Sono tornato oggi dopo un discretamente lungo periodo di vacanza e ho letto quanto scrive con stile cortese cocco81 (che risparmia ben una lettera scrivendo “nn” al posto di “non”, ma che poi però inspiegabilmente dilapida questo piccolo risparmio ottenuto, abbondando con punti esclamativi e punti di domanda).
Svolgendo per Massimo un piccolo lavoro di lettura e proposta di correzione, mi sento chiamato in causa.
Anch’io avevo visto con sospetto e ambiguità l’affermazione a pag. 17: “Ad ogni log switch viene eseguito sempre un checkpoint” e nemmeno lo stralcio di documentazione ufficiale che Massimo riporta basta a convincermi.
Poi ho lasciato cadere la cosa, un po’ per pigrizia e un po’ perché l’argomento checkpoint è uno dei più complicati del funzionamento del database, e il taglio da mera introduzione al funzionamento di Oracle che Massimo intende dare, non richiede tali precisazioni.
Avevo iniziato a raccogliere le idee scrivendo un documento, che pensavo in futuro di proporre al sito Oracle DBA Italia dove spesso intervengo, proprio perché ritengo che anche DBA esperti non abbiano le idee chiare in proposito (e con tale studio contavo pure io di chiarirmele).
Credo che Massimo con checkpoint intenda “full checkpoint” e io per “thread checkpoint” intendo la versione RAC del “full checkpoint” ristretta ad una certa istanza.
Dai miei appunti leggo che: il full checkpoint (e il thread checkpoint) da Oracle8i non si verifica più in occasione di un log switch.
Invece un log switch attiva ancora un particolare checkpoint – che si chiama log switch checkpoint – che NON comporta un flush di TUTTI i dirty buffers e perciò non è un full checkpoint.
Rispetto all’ordinario incremental checkpoint, in cui al termine della scrittura di alcuni buffers, viene solo aggiornato in una variabile in SGA il checkpoint RBA, nel log switch checkpoint il processo CKPT registra il checkpoint SCN nel control file e negli headers dei data files.
cocco81 condividi questa mia spiegazione? Tieni presente che, per poterla scrivere in un paio di righe (omettendo tra l’altro diversi dettagli), ho dovuto dare per scontate conoscenze che in un libro introduttivo a Oracle proprio non c’azzeccano.
18 luglio 2011 alle 11:00 |
In effetti in più di un punto il manuale è volutamente superficiale (e dunque inevitabilmente impreciso) con l’intento di presentare nel modo più semplice possibile concetti invero complicati anche per professionisti molto esperti.
Il titolo stesso del manuale lascia intendere chiaramente che non si tratta di una risorsa per esperti, né per dba in generale. Fermo restando che anche un dba esperto può imparare qualcosa leggendo questo manuale visto che nessuno possiede una conoscenza totale e dunque ogni lettura può dare qualche spunto interessante.
Roberto mi ha già fatto privatamente osservare che forse alcuni passaggi (superficiali) su tematiche di amministrazione potrebbero essere del tutto rimossi per evitare di cadere nel tranello di esporli necessariamente in modo impreciso, tengo molto in considerazione questo consiglio ma al momento ho scelto di lasciarli per dare al lettore inesperto un’idea generale del (complesso) funzionamento del tutto.
In ogni caso aspetto con interesse di leggere lo scritto di Roberto in merito ai checkpoint per imparare qualcosa di più in merito…
Massimo
6 agosto 2011 alle 19:01 |
se avessi una vaga idea di cosa sia un “log switch” o un”redo log ” potrei lasciare un commento anche io . comunque ho scaricato il libro e mi riprometto di leggerlo,in fondo se leggo i geroglifici e la cuneiforme……
ciao fratello…..
6 agosto 2011 alle 21:24 |
non credo che la troverai una lettura troppo divertente…
massimo
18 agosto 2011 alle 12:38 |
Ho dato un’occhiata veloce al libro, trovando alcuni spunti interessanti complimenti! Riguardo al log swich sono andato a riprendermi alcuni appunti e mi ritrovo completamente con quanto scritto da Roberto: from release 8i onward, checkpoints do not occur on log switch.
14 settembre 2011 alle 17:44 |
Mi puoi aiutare a tradurre la query in Oracle?
select * from Test limit 1,20
Grazie
14 settembre 2011 alle 18:59 |
Se la query non è ordinata puoi scrivere semplicemente
Che restituisce 20 righe qualunque.
Se invece la query è ordinata ed usi la LIMIT per la paginazione puoi utilizzare sempre la ROWNUM con una subquery
oppure puoi utilizzare la ROW_NUMBER
select * from ( select test.*, row_number() over (order by qualcosa) rn from Test where rn between 2 and 21;Attenzione in MYSQL il primo parametro della LIMIT (offset) utilizza l’indice 0 per il primo record, quindi la LIMIT che hai scritto vuol dire “venti record a partire dal secondo”…
Per alcuni dettagli su ROWNUM e ROW_NUMBER() puoi fare riferimento all’articolo
http://oracleitalia.wordpress.com/2010/02/20/qualche-parola-su-rownum/
Ciao
15 settembre 2011 alle 11:00 |
Grazie…
28 settembre 2011 alle 14:08 |
Ciao ho un piccolo dubbio.
Creando una tabella in Oracle l’impostazione di default crea i nomi della colonne tutti in maiuscolo.
Ad es. Tabella1(ID,COGNOME,NOME,…)
Come posso avere il risultato seguente:
Ad es. Tabella1(ID,Cognome,Nome,…)
Grazie.
28 settembre 2011 alle 15:00 |
i nomi delle colonne (come anche delle tabelle e di tutti gli altri oggetti del DB) sono case insensitive quindi non è importante se siano maiuscoli o minuscoli tanto poi nei tuoi programmi puoi utilizzarli indifferentemente in maiuscolo o minuscolo. Per questo motivo non vedo la necessità di definire le colonne in minuscolo.
In ogni caso se proprio vuoi definire i nomi delle colonne in minuscolo puoi inserirli nei doppi apici:
Io ritengo che non sia una buona idea perché poi sarai costretto ad utilizzare SEMPRE i doppi apici in SQL
SQL> select cognome from test; select cognome from test * ERRORE alla riga 1: ORA-00904: "COGNOME": identificativo non valido SQL> select Cognome from test; select Cognome from test * ERRORE alla riga 1: ORA-00904: "COGNOME": identificativo non valido SQL> select "Cognome" from test; Nessuna riga selezionataCiao
29 settembre 2011 alle 17:22
Grazie ma ancora non funziona
((((
Se in una tabella del tipo
Cittadinanza(ID, Descrizione)
Ho il record (1,italia)
eseguendo:
select * from Cittadinanza where Descrizione like ‘ITA%’;
non estrae nulla.
Come posso fare?
Grazie per il prezioso aiuto.
29 settembre 2011 alle 18:37 |
Ok ma prima parlavamo dei nomi delle colonne, adesso invece stai parlando dei dati contenuti NELLA tabella, c’è una grossa differenza.
I nomi delle tabelle e delle colonne sono case insensitive come divìcevo ieri. Il contenuto della tabella, invece, è sempre case sensitive.
Se le descrizioni delle nazioni sono in minuscolo ci sono due possibilità: o usi delle costanti alfabetiche in minuscolo oppure utilizzi le funzioni UPPER e LOWER che trasformano una stringa rispettivamente in maiuscolo e minuscolo.
Praticamente:
select * from Cittadinanza where Descrizione like ‘ita%’;
oppure
select * from Cittadinanza where upper(Descrizione) like ‘ITA%’;
La seconda funziona in tutti i casi, anche se non sai se il contenuto della tabella è maiuscolo, minuscolo o mixed.
Il problema è che se sulla colonna Descrizione c’è un indice b-tree (lo standard) la prima query lo può utilizzare, la seconda non può…
ciao
30 settembre 2011 alle 09:15 |
Grazie per il tuo aiuto.
14 ottobre 2011 alle 17:14 |
mizzega… ma quanto ti piace sta roba????
Visto che ti piace così tanto :-p lunedì ti sottoporrò una queretta che avrebbe bisogno di uno sguardo attento…
17 novembre 2011 alle 15:26 |
Ciao Massimo, innanzi tutto vorrei farti i complimenti per questo blog dove spieghi in modo chiaro, completo e comprensibile cose molto interessanti e utili.
Mi sono imbattuto in questo blog solo ieri ma ti ho subito messo tra i preferiti: mi trovo a dover risolvere un problema con un’unica query, e mi sono messo a cercare soluzioni approfondendo l’argomento delle funzioni.
Non avendo trovato ancora il modo di scrivere questa query, mi chiedevo se potessi darmi una mano…?
…posso descriverti il tutto? …eventualmente lo faccio qui di seguito?
17 novembre 2011 alle 19:42 |
si scrivi qui, se è un caso interessante ne potrebbero beneficiare anche altri…
ciao
18 novembre 2011 alle 13:05 |
Grazie.
Cerco di esporre il problema che dovrei risolvere con un’unica query (se è possibile farlo).
Detto brevemente, il punto principale è che si tratta di creare delle coppie di codici, da 2 tabelle, utilizzando ogni singolo codice una sola volta.
Mi spiego meglio entrando nel dettaglio.
Abbiamo 2 tabelle dalla struttura analoga e che sono allo stesso livello: nessuna delle 2 è master dell’altra.
Sono formate da 3 campi: matricola, codice e data inizio.
Il campo matricola rappresenta la principale condizione di join tra le due tabelle (relazione molti a molti); io per semplicità adesso ho inserito i record di una sola matricola.
Il campo codice rappresenta appunto i codici con cui bisogna formare le coppie.
Il campo data inizio rappresenta l’inizio validità del codice; ed è la seconda condizione di join perchè i record di una tabella e dell’altra non devono discostarsi per più di 90 giorni.
PRIMA TABELLA:
—————————————————————————–
CREATE TABLE TAB1
(MATRICOLA1 VARCHAR2(1),
COD1 VARCHAR2(1),
DATA_INI1 DATE);
INSERT INTO TAB1 VALUES(‘X’, ’1′, TO_DATE(’20000101′, ‘YYYYMMDD’));
INSERT INTO TAB1 VALUES(‘X’, ’2′, TO_DATE(’20000601′, ‘YYYYMMDD’));
INSERT INTO TAB1 VALUES(‘X’, ’3′, TO_DATE(’20000601′, ‘YYYYMMDD’));
INSERT INTO TAB1 VALUES(‘X’, ’4′, TO_DATE(’20010101′, ‘YYYYMMDD’));
INSERT INTO TAB1 VALUES(‘X’, ’5′, TO_DATE(’20010301′, ‘YYYYMMDD’));
INSERT INTO TAB1 VALUES(‘X’, ’6′, TO_DATE(’20010415′, ‘YYYYMMDD’));
INSERT INTO TAB1 VALUES(‘X’, ’7′, TO_DATE(’20010415′, ‘YYYYMMDD’));
INSERT INTO TAB1 VALUES(‘X’, ’8′, TO_DATE(’20010615′, ‘YYYYMMDD’));
INSERT INTO TAB1 VALUES(‘X’, ’9′, TO_DATE(’20011015′, ‘YYYYMMDD’));
–***************************************************************************
SECONDA TABELLA:
—————————————————————————–
CREATE TABLE TAB2
(MATRICOLA2 VARCHAR2(1),
COD2 VARCHAR2(1),
DATA_INI2 DATE);
INSERT INTO TAB2 VALUES(‘X’, ‘A’, TO_DATE(’20000701′, ‘YYYYMMDD’));
INSERT INTO TAB2 VALUES(‘X’, ‘B’, TO_DATE(’20010101′, ‘YYYYMMDD’));
INSERT INTO TAB2 VALUES(‘X’, ‘C’, TO_DATE(’20010301′, ‘YYYYMMDD’));
INSERT INTO TAB2 VALUES(‘X’, ‘D’, TO_DATE(’20010501′, ‘YYYYMMDD’));
INSERT INTO TAB2 VALUES(‘X’, ‘E’, TO_DATE(’20020601′, ‘YYYYMMDD’));
–***************************************************************************
A questo punto eseguendo la seguente query ottengo i record relazionati per matricola e differenza di data entro i 90 giorni:
—————————————————————————–
SELECT A.*,
B.*
FROM TAB1 A,
TAB2 B
WHERE A.MATRICOLA1 = B.MATRICOLA2
AND ABS(A.DATA_INI1 – B.DATA_INI2) <= 90;
–***************************************************************************
Le coppie di COD1 E COD2 risultanti da questa query sono:
2 A
3 A
4 B
4 C
5 B
5 C
5 D
6 C
6 D
7 C
7 D
8 D
Adesso nasce il problema: di tutte queste coppie devo riuscire a prenderne solo un sottoinsieme con i seguenti criteri:
- ogni COD1 o COD2 deve essere preso una sola volta in assoluto
- bisogna formare le coppie partendo in ordine di data e nel caso di stessa data prendo il primo codice in ordine alfabetico. Ad esempio tra le coppie 6D, 7D e 8D bisogna prendere la 6D e scartare le 7D e 8D.
Quindi il risultato finale che cerco, e che non riesco a fare con un'unica query, è il seguente:
2 A
4 B
5 C
6 D
Spero di essere riuscito a spiegarmi in modo chiaro… altrimenti chiedi…
Grazie ancora.
18 novembre 2011 alle 23:48 |
Non mi è chiarissimo il requisito perché dice “ogni COD1 o COD2 deve essere preso una sola volta in assoluto” però poi nel risultato atteso mancano del tutto alcuni valori di cod1. Quindi stai facendo comandare il cod2, vuoi un solo valore di cod2 e non vuoi cod1 duplicati, ma possono essere assenti…
Mi limito ad indirizzarti verso le funzioni analitiche.
Questa che segue risolve il tuo problema in questo caso specifico ma non credo vada bane in generale:
Prendila come uno spunto di riflessione, ma soprattutto rifletti sul fatto che è molto più facile gestire l’evoluzione di un programma procedurale semplice che di una query complessa… quindi perché l’esigenza di fare tutto con una query complessa?
Massimo
19 novembre 2011 alle 01:02 |
Intanto cerco di rispondere subito ai tuoi dubbi e spiegarmi meglio …poi mi studio con calma il tuo suggerimento.
Allora la TAB1 ha 9 record e la TAB2 ha 5 record, quindi una join totale produrrebbe 45 record. Mettendo la condizione sulle date a noi risultano quei 12 record di cui prima ho segnalato le 12 coppie.
Da quei 12 bisogna prendere solo quei 4 finali come ho descritto perchè vanno escluse tutte le coppie che contengono o un COD1 o un COD2 già presi in precedenza, quindi partendo dall’inizio:
2 A : è il primo valido e lo prendo. Da adesso in poi nessun’altra coppia che contenga il 2 o la A può essere presa. (OK)
3 A : contiene A e quindi va esclusa per il motivo appena detto (KO)
4 B : entrambi i codici non sono mai già presi e quindi è una coppia valida (OK)
4 C : contiene il 4 che è già preso associato a B, quindi questa coppia va esclusa (KO)
5 B : contiene B che è già preso associato a 4, quindi questa coppia va esclusa (KO)
5 C : sia il 5 che C non sono ancora stati presi in una coppia, quindi questa è valida (OK)
5 D : abbiamo appena preso il 5, quindi questa va esclusa (KO)
6 C : contiene C che è già stato preso col 5, quindi questa va esclusa (KO)
6 D : sia il 6 che D non sono ancora stati presi in una coppia, quindi questa è valida (OK)
7 C, 7 D, 8 D : queste ultime 3 coppie contengono tutte la C o la D che sono state già prese, quindi sono coppie da escludere (KO, KO, KO)
Spero di essermi spiegato meglio, e di aver chiarito ciò che non era chiaro, altrimenti dimmi…
Sapendo questo, il tuo suggerimento resta invariato o per caso c’è una soluzione più specifica?
Sono completamente d’accordo che gestire un algoritmo del genere con una procedura sarebbe molto piu semplice, ma mi è stata fatta la domanda diretta se esiste una query unica capace di farlo e stavo cercando di studiare il caso… e poi mi incuriosisco molto di fronte a casi del genere.
Grazie ancora!!!
19 novembre 2011 alle 01:24 |
PS: Confermo anche che non comanda ne COD1 ne COD2. L’unica regola per prendere o escudere i codici è quella (dopo averli relazionati per matricola e per i 90 gg di distacco) di ordinarli per data, formare le coppie; e poi man mano che si formano le coppie i COD1 e i COD2 presi, faranno escludere qualsiasi altra coppia successiva dove sono presenti.
19 novembre 2011 alle 13:07 |
Stefano non voglio insistere, ma l’algoritmo che hai descritto dipende dall’ordinamento delle coppie, se parti dalle stesse coppie ordinate in modo diverso puoi ottenere risultati diversi. Infatti all’inizio dici “partendo dall’inizio” e poi quando scarti alcuni valori dici “è stato già preso” oppure “non è stato ancora preso”. Ora: uno dei concetti fondamentali dei db relazionali è che in essi i dati non sono ordinati in alcun modo particolare, l’ordinamento lo puoi imporre tu, in fase di estrazione, con una order by. Ma qui veniamo al punto: se nella query che estrae tutte le coppie, prima di scartare quelle che non servono, non metti alcun ordinamento non hai certezza che eseguendola più volte essa estragga i dati sempre nello stesso ordine, e che quindi il ruisultato finale sia deterministico. Se invece metti una order by, puoi ottenere un risultato deterministico ma devi decidere se ordinare prima su cod1 oppure su cod2 e dunque uno dei due campi comanda sull’altro…
In aggiunta c’è un altro problema:l’algoritmo che vuoi implementare richiede di scartare o accettare delle coppie in funzione dei record precedentemente accettati o scartati. Questo per default non è possibile nell’sql standard, dove nessun record puo avere consapevolezza dei dati presenti negli altri record estratti. Ciò non vuol dire che però l’algoritmo non sia implementabile con una query in Oracle. Recentemente infatti sono state introdotte alcune funzionalità che consentono questo tipo di riferimenti incrociati tra diversi record.
Ad esempio la clausola Recursive subquery factoring che consente di realizzare un vero e proprio loop sui dati. Oppure la clausola MODEL su cui ho scritto un articolo in questo blog.
Questa è l’idea che mi sono fatto guardando il problema frettolosamente, ma poiché ci ho dedicato solo pochi minuti magari mi sta sfuggendo qualcosa…
Massimo
19 novembre 2011 alle 13:40 |
Ciao Massimo, innanzi tutto ti ringrazio ancora per il tempo che mi stai dedicando.
Sono completamente d’accordo su tutta la tua premessa, è inequivocabile che sia così nei db relazionali …e quindi giustamente ci vuole un ordinamento.
Infatti l’ordinamento era il mio secondo criterio che ho specificato nel primo commento:
1: <>
2: <>
Quello che hai giustamente notato è che non ho specificato se ordinare prima per la TAB1 o per la TAB2 (in questo senso non c’è una master effettiva), questo perchè non ci sono regole fisse, e quindi per il cliente è irrilevante …anche se questo potrebbe portare a coppie diverse in un caso o nell’altro!
(però ho l’impressione che in realtà il risultato finale non cambi)
Mi rendo conto che è una regola “poco scientifica”, ma questo è il DB che mi ritrovo e questi sono i requisiti …e purtroppo niente di più. Saprai bene che spesso sono situazione fastidiose ma frequenti sopratutto in campo di statistiche come in questo caso.
Ora noi possiamo ordinare per:
DATA_INI1, COD1, DATA_INI2, COD2
come nell’esempio che ho fatto io; oppure possiamo anche ordinare per:
DATA_INI2, COD2, DATA_INI1, COD1
se facessimo così, le famose 12 coppie sarebbero nel seguente ordine:
2 A
3 A
4 B
5 B
4 C
5 C
6 C
7 C
5 D
6 D
7 D
8 D
quindi il sottoinsieme finale che cerchiamo come risultato sarebbe:
2 A
4 B
5 C
6 D
che poi è lo stesso che avevamo con l’ordinamento precedente.
Sicuramente adesso mi voglio studiare bene il tuo primo suggerimento perchè non conosco
<>
e poi mi studierò anche <>.
Mi rendo conto che normalmente le query non considerano i record estratti, ma la questione nasce proprio dal fatto che ho letto la tua interessante spiegazione sulle funzioni analitiche dove dici anche che la loro particolare novità è di andare a lavorare proprio sui record estratti
…da qui nasce il mio dubbio che forse è possibile risolvere il problema con una query…?!?!?!
Qualsiasi altra domanda, considerazione o suggerimento ti venga, non potrà che farmi piacere.
19 novembre 2011 alle 13:43 |
PS: Mi ha cancellato quello che ho scritto tra , avevo scritto:
Sicuramente adesso mi voglio studiare bene il tuo primo suggerimento perchè non conosco
“keep (dense_rank first order by”
e poi mi studierò anche “Recursive subquery factoring”
PPS: Sono spiegati nel tuo libro?
19 novembre 2011 alle 13:46 |
…mamma mia, scusa Massimo, sto facendo un impiccio, mi cancella i simboli di maggiore e minore e ciò che c’è in mezzo.
Allora all’inizio di questo ultimo commento avevo scritto questo:
Infatti l’ordinamento era il mio secondo criterio che ho specificato nel primo commento:
1: “- ogni COD1 o COD2 deve essere preso una sola volta in assoluto”
2: “- bisogna formare le coppie partendo in ordine di data e nel caso di stessa data prendo il primo codice in ordine alfabetico. Ad esempio tra le coppie 6D, 7D e 8D bisogna prendere la 6D e scartare le 7D e 8D”
19 novembre 2011 alle 16:08 |
Stefano mi è chiaro quello che dici ma ti ribadisco che la soluzione può non essere univoca. Ipotizza che le quattro coppie estratte dalla prima join siano (A, 1) (A, 2) (B, 1) (B, 2) e che tutte le date siano uguali, così che non c’è nessuna coppia che è preferenziale perché il numero di giorni di distanza tra le date è minore di altre coppie.
In tal caso rispondono ai tuoi requisiti sia le due coppie (A, 1) (B,2)
che le coppie (A, 2) (B, 1). E non c’è modo di preferire una soluzione all’altra. Otterrai l’una o l’altra soluzione in funzione dell’ordine con cui le 4 coppie di partenza sono estratte. Quindi, ribadisco, o non metti l’order by ottenendo un risultato non deterministico oppure metti l’order by su cod1 o su cod2. In quest’ultimo caso il risultato è deterministico ma uno dei due campi comanda sull’altro…è analizzato per primo… Spero di essermi spiegato…
Ciao
19 novembre 2011 alle 16:42 |
Si esatto, ho capito …stiamo dicendo la stessa identica cosa!
Infatti sin dal primissimo commento ho specificato che bisogna ordinare anche per codice oltre che per data:
“bisogna formare le coppie partendo in ordine di data e NEL CASO DI STESSA DATA PRENDO IL PRIMO CODICE IN ORDINE ALFABETICO. Ad esempio tra le coppie 6D, 7D e 8D bisogna prendere la 6D e scartare le 7D e 8D”
quindi come ho scritto nel commento di poco fa, le 2 order by alternativamente possibili sono su 4 campi:
1: DATA_INI1, COD1, DATA_INI2, COD2
oppure
2: DATA_INI2, COD2, DATA_INI1, COD1
siccome il disegno del db non prevede che una delle tabelle sia master dell’altra, per il cliente è irrilevante quale delle 2 order by viene utilizzata.
Ordinando per tutti questi 4 campi, tra l’altro, sia che venga usata la prima order by che la seconda, comunque anche nell’esempio che hai fatto tu, il risultato sarebbe sempre lo stesso:
A 1
B 2
Quindi adesso il mio problema non è la logica con cui ordinare, che quella è chiara …assodato questo, il mio problema è come scrivere la query che faccia tutto questo…sempre se esiste una query che lo possa fare…?
19 novembre 2011 alle 16:43 |
PS: Trovo molto interessante parlare e approfondire queste cose, spero, solo di non annoiarti troppo vista la tua sicuramente più vasta esperienza e conoscenza della materia.
Grazie!
25 novembre 2011 alle 15:13 |
Ciao, ho studiato tutti gli argomenti che mi hai suggerito e ho trovato una possibile soluzione con le query ricorsive. Tutti argomenti molto interessanti.
Stavo anche cercando di sviluppare il tutto, mi è venuta un’idea e ho provato a buttare giù una bozza di query… ma purtroppo mi sono dovuto fermare a causa del fatto che la versione del DB che usa il cliente è vecchia e non suppurta le query ricorsive, che se non ho capito male sono state introdotte con la versione 11!
Terribile …finalmente si trova una possibile via per la soluzione e sono costretto a fermarmi!
9 dicembre 2011 alle 08:53 |
Ciao Massimo, ho scaricato il tuo libro, sono ormai lontano da un po’ di tempo dal lavoro “tecnico”, ahimè, ma penso che leggere il tuo libro sarà il modo migliore per aggiornarmi.
Un caro saluto
Claudio C.