Archivi tag: select

Firebird: cancellazione dei record duplicati

Potrebbe accadere che all’interno di un database siano presenti una o più tabelle non dotate di chiavi primarie. Questo significa, in soldoni, che è molto alto il rischio di ridondanza (aka duplicati) e quindi di inconsistenza.

Fortunatamente, Firebird ci mette a disposizione un metodo abbastanza semplice per la cancellazione dei duplicati. Esso si basa sull’uso di uno specifico campo (RDB$DB_KEY), il cui valore univoco viene assegnato automaticamente a ciascun record durante la fase di inserimento nel DB.

firebirdlogo.jpg

Inutile dire che preferisco di gran lunga l’uso del suddetto metodo rispetto a soluzioni alternative, in quanto esso si basa esclusivamente su di una query secca e quindi minimizza il rischio di errore. Infatti, se ad esempio avessi utilizzato le cosiddette prepared statements avvelendomi di un qualche linguaggio di alto livello che le supporta (come Java), avrei dovuto scrivere N righe di codice, incrementando la possibilità di incappare in bachi (ecco perchè preferisco sempre mettere in pratica il motto less is more).

Di seguito la query che ho utilizzato:

DELETE FROM TABLE1 t1
WHERE EXISTS (
SELECT 1 FROM TABLE1 t2
WHERE t1.COL1 = t2.COL1 and t1.COL2 = t2.COL2
AND t1.RDB$DB_KEY < t2.RDB$DB_KEY
);

Dove t1 e t2 sono gli alias associati alla medesima tabella, mentre COL1 e COL2 sono i campi che la dovrebbero identificare univocamente (la probabile chiave primaria).

Ora, per avere la certezza che tale query non cancelli più record del previsto, si dovrebbero coinvolgere tutti i campi della tabella. Però, quando il numero dei campi è piuttosto elevato (>15), risulta più conveniente identificare la presunta chiave primaria ed utilizzare solo i campi che concorrono a formarla.

In questo caso, prima di effettuare il DELETE vero e proprio è opportuno fare delle query di verifica.

Ad esempio, dapprima si contano tutti i record della tabella:

SELECT count(*) FROM TABLE1;

e successivamente si individuano i record duplicati:

SELECT COL1, COL2, count(*) FROM TABLE1 GROUP BY COL1, COL2 HAVING count(*) >= 2;

A questo punto il numero dei record a cancellazione avvenuta dovrebbe essere pari al numero restituito dalla prima query meno il numero restituito dalla seconda query.

Per avere la certezza che il numero di record rimossi sia identico alla risultante dell’operazione di differenza effettuata in precedenza si può eseguire la query:

SELECT count(*) FROM TABLE1 t1
WHERE EXISTS (
SELECT 1 FROM TABLE1 t2
WHERE t1.COL1 = t2.COL1 and t1.COL2 = t2.COL2
AND t1.RDB$DB_KEY < t2.RDB$DB_KEY
);

Se il numero di record restituiti è identico al numero dato dalla differenza, abbiamo una buona probabilità che la chiave primaria individuata sia quella giusta (almeno dal punto di vista quantitativo).

Alla prossima.

MySQL: identificare la tabella da cui provengono i dati ricavati mediante una UNION di due SELECT

Qualche giorno fa, mentre scrivevo del codice server-side per un piccolo CRM homemade, ho avuto la necessità di ricavare dei dati mediante la UNION di due SELECT. In particolare, il codice SQL che ho utilizzato è il seguente:

SELECT 'Entrata' AS NomeTabella, O.ID, O.NumeroOperazione, E.Descrizione, E.Tipo, O.Importo, O.DataInserimento, O.DataOperazione FROM entrata AS E, riguarda AS R, operazione AS O WHERE O.ID = R.IDOperazione AND R.IDEntrata = E.ID AND (E.Tipo = 'Cassa' OR E.Tipo = 'Banca') UNION SELECT 'Uscita' AS NomeTabella, O.ID, O.NumeroOperazione, U.Descrizione, U.Tipo, O.Importo, O.DataInserimento, O.DataOperazione FROM uscita AS U, riguarda AS R, operazione AS O WHERE O.ID = R.IDOperazione AND R.IDUscita = U.ID AND (U.Tipo = 'Cassa' OR U.Tipo = 'Banca') ORDER BY DataInserimento
mysql.jpg

Ora, come potete notare le due SELECT vengono applicate su diversi JOIN ed hanno come obiettivo quello di restituire alcuni informazioni importanti, quali il numero dell’operazione finanziaria, la descrizione dell’operazione stessa, il suo importo, ecc. Ovviamente, affinchè i risultati non venissero ripetuti più volte ho utilizzato solo l’operatore UNION (che prevede un DISTINCT implicito) senza la direttiva ALL. Inoltre, per distinguere la tabella di provenienza dei record selezionati, ho creato un ulteriore campo temporaneo, a cui è stato associato l’alias NomeTabella. Così facendo, la struttura della tabella risultante è diventata la seguente:

Nometabella, ID, NumeroOperazione, Descrizione, Tipo, Importo, DataInserimento, DataOperazione

Da quel momento è stato possibile distinguere piuttosto banalmente la tabella di appartenenza dei record visualizzati.

Bye.

NB: affinchè la UNION possa essere applicata è necessario che le due SELECT riguardino lo stesso numero (e tipologie compatibili) di campi.

 

Javascript: campi dinamici mediante innerHTML

Recentemente mi è capitato di dover creare un form in cui inserire più campi di tipo select. Fin qui tutto facile, se non fosse per il fatto che a parte il primo, tutti gli altri campi di questo tipo devono essere “a comparsa”. Per di più, l’unica discriminante in base alla quale viene deciso quale select inserire dinamicamente, si fonda solo ed esclusivamente sull’opzione scelta dall’utente nell’ambito della select immediantamente precedente.

javascript.jpg

 

Ma bando alle ciance, ecco il codice:

function dinamica() {
var tipologia = document.getElementById("tipologia");
if(tipologia.selectedIndex == 1)
{
document.getElementById('parah').innerHTML = "<br><strong>tipo entrata (*): </strong>
<select class='bordo' name='tipoentrata' id='tipoentrata' tabindex='3'>
<option>Seleziona tipo entrata</option>
<option>Finanziamenti</option>
<option>Biglietteria</option>
<option>Servizi</option>
<option>Banche</option>
</select>";
}
else if(tipologia.selectedIndex == 2)
{
document.getElementById('parah').innerHTML = "<br><strong>tipo uscita (*): </strong>
<select class='bordo' name='tipouscita' id='tipouscita' tabindex='3' onchange='javascrip:dinamica()'>
<option>Seleziona tipouscita</option>
<option>Cassa</option>
<option>Banca</option>
<option>Effetti</option>
</select>";
}
else if(tipologia.selectedIndex == 3)
{
document.getElementById('parah').innerHTML = "<br><strong>mastro impegno (*): </strong>
<select class='bordo' name='mastroimpegno' id='mastroimpegno' tabindex='3'>
<option>Seleziona mastro</option>
<?php while($riga = $risultato_mastro_impegno_di_spesa -> fetch_assoc()){?>
<option><?php echo $riga["Nome"]?></option>
<?php } ?>
</select>";
}
}

In particolare, mi sono avvalso dell’innerHTML per inserire stralci di codice HTML in punti ben precisi della pagina, identificati mediante il termine parah.

Se avete qualche dubbio chiedete pure.

A presto.