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

È stato utile?

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.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top