Ich habe eine Tabelle, die protokollierte Ereignisse für gefertigte Artikel enthält. Wir betrachten jedes Ereignis als 2 Status, die auf Details und Berechnungen der zuvor protokollierten Ereignisse für denselben Artikel basieren. Also habe ich eine SELECT-Abfrage entwickelt, die mehrere Self-Joins verwendet, um Faktoren von früheren Ereignissen in Bezug auf jedes Ereignis zu analysieren und die Status zu berechnen. Da diese Abfrage jedoch relativ langsam ist, habe ich zwei Statusspalten hinzugefügt, und ich möchte die Spalten mit den berechneten Status gut aktualisieren, nachdem die Ereignisse eingetreten sind. Auf diese Weise kann ich später in den Statusspalten schnelle Berichte erhalten, anstatt jedes Mal alle Berechnungen durchführen zu müssen.Werte in einer Tabelle basierend auf einer Self-Join-Abfrage zu sich selbst aktualisieren in Oracle
Hier würde mein Tisch sein:
CREATE TABLE ItemLog
(
ItemID decimal(11) NOT NULL,
MessageTime DATE NOT NULL,
Temperature float(7),
Voltage float(7),
Status1 VARCHAR2(10 BYTE),
Status2 VARCHAR2(10 BYTE),
CONSTRAINT "ItemLog_PK" PRIMARY KEY ("ItemID ", "MessageTime ")
);
Meine SELECT Berechnung Abfrage so etwas wie diese:
SELECT ItemID, MessageTime,
CASE WHEN A.Voltage<B.Voltage and A.Voltage<C.Avg_Voltage and C.SD_Voltage<5 THEN 'Good' ELSE 'Bad' END Calculated_Status1,
CASE WHEN A.Temperature<B.Temperature and A.Temperature>C.Temperature and C.SD_Temperature>10 THEN 'Good' ELSE 'Bad' END Calculated_Status2
FROM ItemLog A,
(SELECT F.ItemID,
F.MessageTime Key_MessageTime,
S.Voltage,
S.Temperature
FROM ItemLog F,
ItemLog S
WHERE F.ItemID=S.ItemID
and S.MessageTime=
SELECT MAX(MessageTime)
FROM ItemLog
WHERE ItemID=F.ItemID
and MessageTime<F.MessageTime
and Voltage<12
and Temperature<125
) B, -- Returns the Voltage and Temperature from the prior time it was <12 and <125
(SELECT K.ItemID, K.MessageTime,
AVG(L.Temp) Avg_Temperature, STDDEV(L.Temperature) SD_Temp,
AVG(L.Voltage) Avg_Voltage, STDDEV(L.Voltage) SD_Voltage
FROM ItemLog K,
ItemLog L
WHERE K.ItemID=L.ItemID
and L.MessageTime=
SELECT MAX(MessageTime)
FROM ItemLog
WHERE ItemID=K.ItemID
and MessageTime<K.MessageTime
GROUP BY K.ItemID, K.MessageTime
) C -- Returns the Voltage and Temperature stats from all prior messages
(SELECT ItemID
FROM ItemLog
WHERE Voltage>40
) D -- Returns all ItemID where Voltage was ever >40, to exclude them
WHERE A.ItemID=B.ItemID and A.MessageTime=B.MessageTime
and A.ItemID=C.ItemID and A.MessageTime=C.MessageTime
and A.ItemID=D.ItemID(+) and D.ItemID IS NULL
Also, die Frage ist, wie kann ich die Status1 und Status2 Spalten in der Aktualisierung Tabelle soll die Spalten Calculated_Status1 und Calculated Status2 sein? Ich habe versucht, meine Berechnungsabfrage zu nehmen und sie mit den 2 Primärschlüsseln zur Tabelle zu verbinden, aber ich bekomme den Fehler "ORA-01779: kann eine Spalte nicht ändern, die einer nicht Schlüssel-konservierten Tabelle zuordnet".
UPDATE (
SELECT U.*,
V.Calculated_Status1
V.Calculated_Status2
FROM ItemLog U,
(<calculation query above>) V
WHERE U.ItemID=V.ItemID and U.MessageTime=V.MessageTime)
SET U.Status1=V.CalculatedStatus1,
U.Status2=V.CalculatedStatus2
Ich könnte ein Update mit einem SET Status1=(SELECT...
vorstellen, aber das wäre eine Art korrelierte WHERE für die ItemID und Messagetime benötigt, und ich es schrecklich langsam läuft erwarten würde. Es scheint, dass es einen direkteren Weg geben sollte, dies zu tun?
Ich würde vorschlagen, dass Sie eine andere Frage mit Beispieldaten und gewünschten Ergebnissen stellen. Es ist durchaus möglich, dass Ihre Abfrage beschleunigt wird, ohne neue Spalten zu erstellen. –