一直试图围绕如何在此表中设置Duration
包括我的头,与一个查询,这是行的时间戳和前一行的值为SkillTargetID
。我发现了一些类似的问题(this one特别有用),但他们都能够预测第二行的距离,例如,基于月份值。对于我的每一行数据,其“姐妹”行可能与它相邻,或者不相邻。设置列之间的差值行之间的行数不确定的行之间的差异
这里是我的表在这个例子中的简化版本:
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 |
+----+---------------+--------------+----------+
该表中的基础数据符合此规则:当id
有序的UTC_DateTime
值将始终大于或等于到上一行,如这个示例数据所示。具有相同UTC_DateTime
的不同SkillTargetID
值的顺序不可预测,并且许多行将具有相同的UTC_DateTime
和SkillTargetID
(如16和17)。
我想出了迄今为止最好的尝试包括子查询找到以前的相关行,如果存在的话(我也选择了第二UTC_DateTime
所以你可以看到什么是被减去):
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 |
+----+---------------+--------------+---------------+----------+
很明显,像这样的UPDATE会随着这个表的增长而变得非常快。这是所有我能想出来之前围绕回圈:
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
我还有什么其他的选择?
下面是我用的测试数据:
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);
奖金 - 是否有可能做到这一点,同时插入新的多行数据,如果它包括有序id
了吗?如期间:
INSERT INTO testdur (id,SkillTargetID,UTC_DateTime) VALUES
(19,5010,1323719505),
(20,5055,1323719510);
感谢您提前帮忙!
我最后做的大部分的这个代码,而不是SQL,但是哟你的想法确实奏效 - 我测试了它。不过,我可能会将这个想法用于其他方面。感谢您抽出宝贵的时间。 – aparker 2012-04-25 20:18:04