Ich habe versucht, in dieser Tabelle Duration
zu setzen, mit einer einzigen Abfrage, das ist der Unterschied zwischen dem Timestamp der Zeile und die vorherige Reihe der gleichen SkillTargetID
Wert. Ich fand bereits einige ähnliche Fragen (this one war besonders hilfreich), aber sie alle waren in der Lage zu sagen, wie weit die zweite Reihe entfernt ist, zum Beispiel basierend auf einem Monat. Für jede Zeile meiner Daten könnte die "Schwester" -Reihe daneben liegen oder nicht. HierSetzen einer Spalte auf einen Unterschied zwischen Zeilen Werte mit einer unbestimmten Anzahl von Zeilen zwischen ihnen
ist eine verkleinerte Version meiner Tabelle für dieses Beispiel:
mysql> select * from testdur order by id;
+----+---------------+--------------+----------+
| id | SkillTargetID | UTC_DateTime | Duration |
+----+---------------+--------------+----------+
| 1 | 5000 | 1323719341 | NULL |
| 2 | 5010 | 1323719341 | NULL |
| 3 | 5000 | 1323719342 | NULL |
| 4 | 5010 | 1323719342 | NULL |
| 5 | 5000 | 1323719343 | NULL |
| 6 | 5055 | 1323719345 | NULL |
| 7 | 5010 | 1323719350 | NULL |
| 8 | 5010 | 1323719441 | NULL |
| 9 | 5010 | 1323719444 | NULL |
| 10 | 5000 | 1323719445 | NULL |
| 11 | 5055 | 1323719445 | NULL |
| 12 | 5060 | 1323719445 | NULL |
| 13 | 5000 | 1323719445 | NULL |
| 14 | 5010 | 1323719445 | NULL |
| 15 | 5060 | 1323719446 | NULL |
| 16 | 5000 | 1323719460 | NULL |
| 17 | 5000 | 1323719460 | NULL |
| 18 | 5060 | 1323719500 | NULL |
+----+---------------+--------------+----------+
Die Basisdaten in der Tabelle zu dieser Regel hält: Wenn nach dem id
bestellt, werden die Werte von UTC_DateTime
wird immer größer oder gleich zur vorherigen Reihe, wie diese Beispieldaten zeigen. Die Reihenfolge der verschiedenen SkillTargetID
Werte mit der gleichen UTC_DateTime
ist nicht vorhersehbar, und viele Zeilen haben die gleichen UTC_DateTime
und SkillTargetID
(wie 16 und 17).
Der beste Versuch, den ich mit so gekommen sind weit enthält eine Unterabfrage der vorherigen zugehörigen Zeile zu finden, wenn es vorhanden ist (ich die zweite UTC_DateTime
so kann auch ausgewählt Sie sehen, was abgezogen wird):
SELECT
t.id,
t.SkillTargetID,
t.UTC_DateTime,
t2.UTC_DateTime AS UTC_DateTime2,
(CASE WHEN t2.UTC_DateTime IS NULL THEN 0 ELSE t.UTC_DateTime - t2.UTC_DateTime END) AS Duration
FROM testdur t LEFT JOIN testdur t2
ON t.SkillTargetID = t2.SkillTargetID
AND t2.id = (
SELECT id FROM testdur
WHERE SkillTargetID = t.SkillTargetID AND id < t.id
ORDER BY id DESC
LIMIT 1)
ORDER BY t.id;
+----+---------------+--------------+---------------+----------+
| id | SkillTargetID | UTC_DateTime | UTC_DateTime2 | Duration |
+----+---------------+--------------+---------------+----------+
| 1 | 5000 | 1323719341 | NULL | 0 |
| 2 | 5010 | 1323719341 | NULL | 0 |
| 3 | 5000 | 1323719342 | 1323719341 | 1 |
| 4 | 5010 | 1323719342 | 1323719341 | 1 |
| 5 | 5000 | 1323719343 | 1323719342 | 1 |
| 6 | 5055 | 1323719345 | NULL | 0 |
| 7 | 5010 | 1323719350 | 1323719342 | 8 |
| 8 | 5010 | 1323719441 | 1323719350 | 91 |
| 9 | 5010 | 1323719444 | 1323719441 | 3 |
| 10 | 5000 | 1323719445 | 1323719343 | 102 |
| 11 | 5055 | 1323719445 | 1323719345 | 100 |
| 12 | 5060 | 1323719445 | NULL | 0 |
| 13 | 5000 | 1323719445 | 1323719445 | 0 |
| 14 | 5010 | 1323719445 | 1323719444 | 1 |
| 15 | 5060 | 1323719446 | 1323719445 | 1 |
| 16 | 5000 | 1323719460 | 1323719445 | 15 |
| 17 | 5000 | 1323719460 | 1323719460 | 0 |
| 18 | 5060 | 1323719500 | 1323719446 | 54 |
+----+---------------+--------------+---------------+----------+
Offensichtlich wird ein UPDATE wie dieses schnell böse, wenn dieser Tisch wächst. Das ist alles, was ich tun kann, bevor im Kreis wieder um:
UPDATE testdur t SET t.Duration = t.UTC_DateTime - (
SELECT UTC_DateTime FROM testdur
WHERE SkillTargetID = t.SkillTargetID AND id < t.id
ORDER BY id DESC LIMIT 1);
ERROR 1093 (HY000): You can't specify target table 't' for update in FROM clause
Welche anderen Möglichkeiten habe ich?
Hier ist die Testdatum war ich mit:
CREATE TABLE `testdur` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`SkillTargetID` int(10) unsigned NOT NULL,
`UTC_DateTime` int(10) unsigned NOT NULL,
`Duration` int(10) unsigned DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
INSERT INTO testdur (SkillTargetID,UTC_DateTime) VALUES (5000,1323719341),(5010,1323719341),(5000,1323719342),(5010,1323719342),(5000,1323719343),(5055,1323719345),(5010,1323719350),(5010,1323719441),(5010,1323719444),(5000,1323719445),(5055,1323719445),(5060,1323719445),(5000,1323719445),(5010,1323719445),(5060,1323719446),(5000,1323719460),(5000,1323719460),(5060,1323719500);
BONUS - Ist es möglich, dies zu tun, während neue mehrreihigen Einfügen von Daten, wenn sie die id
bereits bestellt enthalten? Wie zum Beispiel:
INSERT INTO testdur (id,SkillTargetID,UTC_DateTime) VALUES
(19,5010,1323719505),
(20,5055,1323719510);
Danke für die Hilfe vor der Zeit!
ich die meisten dieser in Code anstelle von SQL-ended zu tun, aber yo Deine Idee funktioniert - ich habe es getestet.Ich werde wahrscheinlich diese Idee für andere Dinge verwenden können. Danke, dass du dir die Zeit genommen hast. – aparker