2010-08-06 69 views
0

我有一個表的輸入和派生表參數如何在下面的PostgreSQL查詢中解決代碼重複?

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) 
); 

以下查詢檢查的參數是否已經改變,或不存在還沒有,並插入一個新的值的參數。

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); 
} 

我應該如何最好地解決MyParameter子查詢的重複?

清理此類查詢的任何其他提示

+0

您是否在兩個表中插入了相同的可配置名稱和時間。您已在參數中引用輸入的外鍵。你真的需要去正常化嗎? – 2010-08-06 12:13:02

+0

增加了可配置的定義。一個可配置的有一個輸入列表,一個輸入可以是一個參數。我選擇了對它進行反規範化處理,以便從Inputs表中輕鬆獲得概覽。 (有更多的表來源於輸入和參數) – Pieter 2010-08-06 13:16:43

回答

3

您應該避免使用非規範化表格。您應該使用視圖來輕鬆瀏覽參數表。這會更容易。

如果您的視圖速度不夠快,您應該只使用非標準化彙總表。但是任何非規範化表格都應該使用觸發器進行維護,否則您可能會冒這個表格不同步的風險。

爲此,您可以在Parameters上創建一個觸發器,將upsert轉換成插入時的Inputs。如果您曾刪除或更新Parameters上的這些列,那麼維護Inputs會很複雜。當Parameters中沒有相應的行時,您必須刪除行 - 您需要維護Inputs中的計數,以瞭解Parameters中沒有對應的行。併發插入/更新/刪除性能將會變差,因爲Parameters中的任何更改都必須阻止Inputs中的一行。這一切都是醜陋和壞 - 一個觀點是更好的解決方案。