Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/67.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Mysql 将列设置为行与行之间的差值值,且行之间的行数不确定_Mysql_Sql - Fatal编程技术网

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