Come risolvere la duplicazione del codice nella seguente query PostgreSQL?
-
26-09-2019 - |
Domanda
Ho una tabella Input e una tabella derivata Parametri
CREATE TABLE Configurables
(
id SERIAL PRIMARY KEY
);
CREATE TABLE Inputs
(
configurable integer REFERENCES Configurables( id ),
name text,
time timestamp,
PRIMARY KEY( configurable, name, time )
);
CREATE TABLE Parameters
(
configurable integer,
name text,
time timestamp,
value text,
FOREIGN KEY( configurable, name, time ) REFERENCES Inputs( configurable, name, time )
);
La query seguente controlla se un parametro è stato modificato o non è ancora presente e inserisce il parametro con un nuovo valore.
QString PostgreSQLQueryEngine::saveParameter( int configurable, const QString& name, const QString& value )
{
return QString( "\
INSERT INTO Inputs( configurable, name, time ) \
WITH MyParameter AS \
( \
SELECT configurable, name, time, value \
FROM \
( \
SELECT configurable, name, time, value \
FROM Parameters \
WHERE (configurable = %1) AND (name = '%2') AND time = \
( \
SELECT max( time ) \
FROM Parameters \
WHERE (configurable = %1) AND (name = '%2') \
) \
UNION \
SELECT %1 AS configurable, '%2' AS name, '-infinity' AS time, NULL AS value \
)AS foo \
) \
SELECT %1 AS configurable, '%2' AS name, 'now' AS time FROM MyParameter \
WHERE time = (SELECT max(time) FROM MyParameter) AND (value <> '%3' OR value IS NULL); \
\
INSERT INTO Parameters( configurable, name, time, value ) \
WITH MyParameter AS \
( \
SELECT configurable, name, time, value \
FROM \
( \
SELECT configurable, name, time, value \
FROM Parameters \
WHERE (configurable = %1) AND (name = '%2') AND time = \
( \
SELECT max( time ) \
FROM Parameters \
WHERE (configurable = %1) AND (name = '%2') \
) \
UNION \
SELECT %1 AS configurable, '%2' AS name, '-infinity' AS time, NULL AS value \
)AS foo \
) \
SELECT %1 AS configurable, '%2' AS name, 'now' AS time, '%3' AS value FROM MyParameter \
WHERE time = (SELECT max(time) FROM MyParameter) AND (value <> '%3' OR value IS NULL); \
" ).arg( configurable ).arg( name ).arg( value );
}
Come dovrei risolvere al meglio la duplicazione di 2 sottoquery MyParameter?
Eventuali altri suggerimenti su come ripulire una query come questa
Soluzione
Dovresti evitare tabelle denormalizzate.È necessario utilizzare una vista per una facile panoramica della tabella dei parametri.Sarebbe molto, molto più semplice.
Dovresti utilizzare la tabella di riepilogo denormalizzata solo se la tua visualizzazione non è abbastanza veloce.Ma eventuali tabelle denormalizzate dovrebbero essere mantenute utilizzando i trigger, altrimenti si rischia che queste tabelle non siano sincronizzate.
Per questo puoi creare un trigger on Parameters
quello sarà upsert in Inputs
sull'inserto.Se mai elimini o aggiorni queste colonne su Parameters
quindi mantenendo Inputs
sarebbe complicato.Dovresti eliminare le righe quando non è presente alcuna riga corrispondente Parameters
- dovresti mantenere i conteggi Inputs
, per sapere quando non è presente alcuna riga corrispondente Parameters
.Le prestazioni simultanee di inserimento/aggiornamento/eliminazione faranno schifo, così come qualsiasi modifica in Parameters
dovrà bloccare una riga Inputs
.Tutto questo è brutto e brutto: una visione è una soluzione molto migliore.