Mysql 将列设置为行与行之间的差值值,且行之间的行数不确定
我一直在想如何在这个表中设置Mysql 将列设置为行与行之间的差值值,且行之间的行数不确定,mysql,sql,Mysql,Sql,我一直在想如何在这个表中设置Duration,只需一个查询,即行的时间戳与相同SkillTargetID值的前一行之间的差异。我已经发现了一些类似的问题(特别有用),但它们都能够预测第二行的距离,例如,基于月份值。对于我的数据的每一行,它的“姊妹”行可能与其相邻,也可能不相邻 以下是本例中我的表格的简化版本: mysql> select * from testdur order by id; +----+---------------+--------------+----------+
Duration
,只需一个查询,即行的时间戳与相同SkillTargetID
值的前一行之间的差异。我已经发现了一些类似的问题(特别有用),但它们都能够预测第二行的距离,例如,基于月份值。对于我的数据的每一行,它的“姊妹”行可能与其相邻,也可能不相邻
以下是本例中我的表格的简化版本:
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\u DateTime
的值将始终大于或等于上一行,如本示例数据所示。不同的SkillTargetID
值与相同的UTC\u日期时间
的顺序是不可预测的,许多行将具有相同的UTC\u日期时间
和SkillTargetID
(例如16和17)
到目前为止,我提出的最佳尝试包括一个子查询,以查找上一个关联行(如果它存在的话)(我还选择了第二个UTC_DateTime
,以便您可以看到要减去的内容):
奖金-如果插入新的多行数据时已经包含订购的id
,是否可以这样做?例如:
INSERT INTO testdur (id,SkillTargetID,UTC_DateTime) VALUES
(19,5010,1323719505),
(20,5055,1323719510);
提前谢谢你的帮助 通过实现@mysql变量,您可能可以简化它。预查询以获取ID以及与之关联的下一个ID,然后对原始表进行两次连接(不同的别名)以获得正确的值,然后执行所需的任何计算。。。因此,“LastID”列是@WasLastID值的任意值,如果它在相同的技能目标ID限定范围内。如果不是,它将被设置回零。应用该测试后,@WasLastID获取当前记录的ID,作为下一个条目测试的基础
select
t.id,
t.SkillTargetID,
t.UTC_DateTime,
t.UTC_DateTime2,
if( @WasLastTarget = t.SkillTargetID, @WasLastID, 0 ) LastID,
@WasLastID := t.ID as tmpLastID,
@WasLastTarget := t.SkillTargetID as tmpLastTarget
from
testdur t,
( select @WasLastID = 0,
@WasLastTarget := 0 ) sqlvars
order by
t.skillTargetID,
t.id
order by将在处理任何@变量之前应用于结果集,因此上述查询实质上将创建以下结果,确保在应用@last target比较时所有技能目标都正确排序
+----+---------------+--------------+--------+------------+---------------+
| id | SkillTargetID | UTC_DateTime | LastID | tmpLastID | tmpLastTarget |
+----+---------------+--------------+--------+------------+---------------+
| 1 | 5000 | 1323719341 | 0 | 1 | 5000
| 3 | 5000 | 1323719342 | 1 | 3 | 5000
| 5 | 5000 | 1323719343 | 3 | 5 | 5000
| 10 | 5000 | 1323719445 | 5 | 10 | 5000
| 13 | 5000 | 1323719445 | 10 | 13 | 5000
| 16 | 5000 | 1323719460 | 13 | 16 | 5000
| 17 | 5000 | 1323719460 | 16 | 17 | 5000
-- BREAK BETWEEN SKILL TARGET...
| 2 | 5010 | 1323719341 | 0 | 2 | 5010
| 4 | 5010 | 1323719342 | 2 | 4 | 5010
| 7 | 5010 | 1323719350 | 4 | 7 | 5010
| 8 | 5010 | 1323719441 | 7 | 8 | 5010
| 9 | 5010 | 1323719444 | 8 | 9 | 5010
| 14 | 5010 | 1323719445 | 9 | 14 | 5010
-- BREAK BETWEEN SKILL TARGET...
| 6 | 5055 | 1323719345 | 0 | 6 | 5055
| 11 | 5055 | 1323719445 | 6 | 11 | 5055
-- BREAK BETWEEN SKILL TARGET...
| 12 | 5060 | 1323719445 | 0 | 12 | 5060
| 15 | 5060 | 1323719446 | 12 | 15 | 5060
| 18 | 5060 | 1323719500 | 15 | 18 | 5060
+----+---------------+--------------+--------+------------+---------------+
现在,所有所说的和提供的样本,你们可以在上面扩展,比如
select
PreQuery.*,
CASE WHEN t1.UTC_DateTime IS NULL THEN 0
ELSE t2.UTC_DateTime - t1.UTC_DateTime END) AS Duration
from
( above full select query ) as PreQuery
LEFT JOIN testdur t1
on PreQuery.ID = t1.ID
LEFT JOIN testdur t2
on PreQuery.LastID = t2.ID
我用代码而不是SQL完成了大部分工作,但你的想法确实有效——我已经测试过了。不过,我可能会把这个想法用在其他事情上。谢谢你抽出时间。
select
t.id,
t.SkillTargetID,
t.UTC_DateTime,
t.UTC_DateTime2,
if( @WasLastTarget = t.SkillTargetID, @WasLastID, 0 ) LastID,
@WasLastID := t.ID as tmpLastID,
@WasLastTarget := t.SkillTargetID as tmpLastTarget
from
testdur t,
( select @WasLastID = 0,
@WasLastTarget := 0 ) sqlvars
order by
t.skillTargetID,
t.id
+----+---------------+--------------+--------+------------+---------------+
| id | SkillTargetID | UTC_DateTime | LastID | tmpLastID | tmpLastTarget |
+----+---------------+--------------+--------+------------+---------------+
| 1 | 5000 | 1323719341 | 0 | 1 | 5000
| 3 | 5000 | 1323719342 | 1 | 3 | 5000
| 5 | 5000 | 1323719343 | 3 | 5 | 5000
| 10 | 5000 | 1323719445 | 5 | 10 | 5000
| 13 | 5000 | 1323719445 | 10 | 13 | 5000
| 16 | 5000 | 1323719460 | 13 | 16 | 5000
| 17 | 5000 | 1323719460 | 16 | 17 | 5000
-- BREAK BETWEEN SKILL TARGET...
| 2 | 5010 | 1323719341 | 0 | 2 | 5010
| 4 | 5010 | 1323719342 | 2 | 4 | 5010
| 7 | 5010 | 1323719350 | 4 | 7 | 5010
| 8 | 5010 | 1323719441 | 7 | 8 | 5010
| 9 | 5010 | 1323719444 | 8 | 9 | 5010
| 14 | 5010 | 1323719445 | 9 | 14 | 5010
-- BREAK BETWEEN SKILL TARGET...
| 6 | 5055 | 1323719345 | 0 | 6 | 5055
| 11 | 5055 | 1323719445 | 6 | 11 | 5055
-- BREAK BETWEEN SKILL TARGET...
| 12 | 5060 | 1323719445 | 0 | 12 | 5060
| 15 | 5060 | 1323719446 | 12 | 15 | 5060
| 18 | 5060 | 1323719500 | 15 | 18 | 5060
+----+---------------+--------------+--------+------------+---------------+
select
PreQuery.*,
CASE WHEN t1.UTC_DateTime IS NULL THEN 0
ELSE t2.UTC_DateTime - t1.UTC_DateTime END) AS Duration
from
( above full select query ) as PreQuery
LEFT JOIN testdur t1
on PreQuery.ID = t1.ID
LEFT JOIN testdur t2
on PreQuery.LastID = t2.ID