• UNION

    Gli operatori UNION e UNION ALL in Oracle

    In questo articolo vedremo le caratteristiche degli operatori insiemistici UNION e UNION ALL di Oracle e le loro differenze.

    Le tabelle usate per gli esempi per gli operatori UNION e UNION ALL

    In un precedente articolo dal titolo “Gli operatori set” abbiamo introdotto gli operatori insiemistici e le loro caratteristiche. In questo articolo, dal taglio più operativo, ne  affronteremo due nello specifico: UNION e UNION ALL.

    Gli esempi che riporto fanno riferimento a due tabelle create appositamente: OLD_DEPT e NEW_DEPT. La tabella OLD_DEPT rappresenta una tabella creata con una vecchia versione di Oracle. I campi della tabella sono:

    • dated di tipo DATE (supponiamo che non era disponibile TIMESTAMP nella vecchia versione);
    • deptno di tipo NUMBER (anche con decimali);
    • dname di tipo CHAR (supponiamo che non era disponibile VARCHAR2 a lunghezza variabile nella vecchia versione);

    La tabella NEW_DEPT rappresenta una tabella creata con una nuova versione di Oracle. I campi della tabella sono:

    • started di tipo TIMESTAMP(6) (che può memorizzare per default data e ora con sei decimali di precisione sui secondi);
    • deptid di tipo NUMBER(38) (un NUMBER con fino a 38 cifre significative, non decimale);
    • dname di tipo VARCHAR2 (più performante in termini di spazio rispetto a CHAR);

    Lo script di creazione delle tabella e popolamento delle tabelle sarà il seguente:

    CREATE TABLE old_dept (
     dated DATE,
     deptno NUMBER,
     dname CHAR(20)
    ); 
    
    CREATE TABLE new_dept (
     started TIMESTAMP(6),
     deptid NUMBER(38),
     dname VARCHAR2(14)
    ); 
    
    alter session set nls_date_format = 'dd/MON/yyyy hh24:mi:ss';
    
    INSERT INTO old_dept(dated, deptno, dname) VALUES ('09-DIC-2016 16:00:11', 10, 'Accounts');
    INSERT INTO old_dept(dated, deptno, dname) VALUES ('09-DIC-2016 16:00:32', 20, 'Support');
    INSERT INTO new_dept(started, deptid, dname) VALUES (TO_TIMESTAMP('09-DIC-2016 16:01:19'), 10, 'Accounts');
    INSERT INTO new_dept(started, deptid, dname) VALUES (TO_TIMESTAMP('09-DIC-2016 16:01:45'), 30, 'Admin');

    Di seguito il risultato dell’interrogazione della tabella old_dept

    old_dept

    e di quella new_dept.

    new_dept

     

    L’operatore UNION ALL

    L’operatore UNION ALL prende due result set e li concatena insieme in un unico result set. I result set provengono da due query che devono selezionare lo stesso numero di colonne; le colonne corrispondenti delle due query (nell’ordine in cui vengono specificate) devono essere dello stesso gruppo di tipo di dati (ad esempio DATE con TIMESTAMP oppure CHAR con VARCHAR2). Le colonne non devono avere necessariamente gli stessi nomi.

    UNION-ALL

    Il risultato di questa query composta è il seguente:

    UNION-ALL-risultato

    La UNION ALL delle due tabelle converte tutti i valori al più alto livello di precisione: i campi DATE vengono trasformati in TIMESTAMP (i tipi DATE vengono riempiti con degli zeri), i campi CHAR vengono trasformati in VARCHAR2 con la lunghezza della colonna di input più lunga, ed i numeri accetteranno decimali. L’ordine delle righe viene dalle righe della prima tabella, in qualunque ordine sono stati memorizzati, seguito dalle righe della seconda tabella in qualsiasi ordine in cui sono stati memorizzati.

    Per impostazione predefinita, l’output di un query UNION ALL composta non è ordinato. Se si vuole ordinare l’insieme di risultati, occorre specificare una clausola ORDER BY alla fine dell’istruzione.

     

    L’operatore UNION

    L’operatore UNION esegue un UNION ALL e poi ordina il risultato in tutte le colonne e rimuove i duplicati.

    UNION

    Questa query restituisce tutte le quattro righe perché ci sono duplicati, ordinate (in ordine crescente) a partire dal primo campo depno, poi per dname e infine per dated.

    UNION-risultato

    Può sembrare che le prime due righe non sono in ordine per i valori in DATED, ma in realtà lo sono sono: il campo DNAME nella tabella OLD_DEPT è lungo 20 byte (riempito con gli spazi), mentre il DNAME in NEW_DEPTS, dove è un VARCHAR2, è lungo quanto è lungo il nome. Gli spazi danno alla riga di OLD_DEPT un valore di ordinamento superiore, anche anche se il valore di data è inferiore.

    UNION

    Quest’altra query rimuove gli spazi iniziali e finali dalla colonna DNAME e tronca gli elementi DATED e STARTED. Due righe così diventano identiche, e così solo una appare nell’output.

    UNION-risultato
    Poiché il risultato viene ordinato, l’ordine originale delle singole query in una UNION non fa alcuna differenza: viene applicato al risultato finale l’ordinamento di default dell’operatore UNION.

     

    Giulio Cantali – IT Consultant

    Creatore di Database Master, il primo percorso per diventare esperti di database

Lascia un commento

Se vuoi condividere la tua opinione, lascia un commento

Puoi usare questi tag e attributi: HTML:

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">