如果标题不够具有描述性,请原谅 这是我的问题场景:
我有一个包含以下列(组成)的表:
oid rev state time
1 0 S T1
2 0 S T2
1 0 A T3
2 0 A T4
2 1 MS T5
2 1 MA T6
2 1 M T7
2 2 MS T8
2 2 M T9
时间列是varchar(包含日期/时间)
我需要找到每个订单从状态转换到状态所需的时间 - 有效状态转换定义为:
S->A
MS->MA
MS-M
(即,转换可以是从提交到确认,修改提交到修改确认或修改提交到修改) MS可以转换为MA,然后转换为M,但我只对从MS到MA的过渡感兴趣。
在上面:
oid 1 transitioned from S to A.
oid 2 changed from S to A (rev 0)
oid 2 changed from MS to MA (rev 1) - here we don't want to consider transition to M
oid 2 changed from MS to M (rev 2)
因此查询输出应如下所示(timeTaken将以毫秒为单位):
oid rev timeTaken state
1 0 (T3-T1) A
2 0 (T4-T2) A
2 1 (T6-T5) MA
2 2 (T9-T8) M
因此,如果当前记录状态是MA或M,则仅当前一记录状态为MS时才需要计算时间差(假设这是按照oid,rev,time排序)。如果当前记录状态为M,则跳过前一记录状态为MA。
无论如何使用mysql中的sql查询来执行此操作。任何指针都会有所帮助。感谢。
====
该表以时间为主键。
我有这个查询以正确的方式订购它(如果它有任何帮助)
按顺序选择oid,rev,state,time by orderid,time,rev
将给出:
oid rev州时间
1 0 S T1
1 0 A T3
2 0 S T2
2 0 A T4
2 1 MS T5
2 1 MA T6
2 1 M T7
2 2 MS T8
2 2 M T9
答案 0 :(得分:0)
嗯,我认为这是你应该在代码中做的事情,而不是你的数据库。
我可以想办法用SQL做到这一点,但它有点复杂。
它是这样的。假设您的原始表格为t1
。
创建一个视图,其中包含每个oid,rev。
中的所有可能转换create view transitions as
select a.oid, a.rev, a.state as state_from, b.state as state_to,
a.time as time_from, b.time as time_to
from t1 as a, t1 as b
where a.oid=b.oid
and a.rev=b.rev
and a.time<b.time;
+------+------+------------+----------+-----------+---------+
| oid | rev | state_from | state_to | time_from | time_to |
+------+------+------------+----------+-----------+---------+
| 1 | 0 | S | A | T1 | T3 |
| 2 | 0 | S | A | T2 | T4 |
| 2 | 1 | MS | MA | T5 | T6 |
| 2 | 1 | MS | M | T5 | T7 |
| 2 | 1 | MA | M | T6 | T7 |
| 2 | 2 | MS | M | T8 | T9 |
+------+------+------------+----------+-----------+---------+
(注意:此步骤不是必需的,但出于教育目的!)剪掉时间不连续的所有内容。它通过为每个time_to
取最小time_from
的行来实现此目的(因此需要T5->T6
代替T5->T7
)
select a.*
from transitions as a
join (
select oid, rev, time_from, min(time_to) as time_to
from transitions
group by time_from
) as b
on a.oid=b.oid and a.rev=b.rev
and a.time_from=b.time_from and a.time_to=b.time_to;
+------+------+------------+----------+-----------+---------+
| oid | rev | state_from | state_to | time_from | time_to |
+------+------+------------+----------+-----------+---------+
| 1 | 0 | S | A | T1 | T3 |
| 2 | 0 | S | A | T2 | T4 |
| 2 | 1 | MS | MA | T5 | T6 |
| 2 | 1 | MA | M | T6 | T7 |
| 2 | 2 | MS | M | T8 | T9 |
+------+------+------------+----------+-----------+---------+
现在您只想选择time_from-time_to
其中state_from
和state_to
是您感兴趣的转化。您可以将其与上一个查询结合使用,以便执行第2步。没有必要(步骤2中唯一新的东西是最后和/或/或位):
select a.oid,a.rev,a.state_to as state,a.time_to-a.time_from as timeTaken
from transitions as a
join (
select oid, rev, time_from, min(time_to) as time_to
from transitions
group by time_from
) as b
on a.oid=b.oid and a.rev=b.rev
and a.time_from=b.time_from and a.time_to=b.time_to
and ( (a.state_from='S' and a.state_to='A')
or (a.state_from='MS' and a.state_to='MA')
or (a.state_from='MS' and a.state_to='M')
);
+------+------+-------+-----------+
| oid | rev | state | timeTaken |
+------+------+-------+-----------+
| 1 | 0 | A | T3-T1 |
| 2 | 0 | A | T4-T2 |
| 2 | 2 | M | T6-T5 |
| 2 | 1 | MA | T9-T8 |
+------+------+-------+-----------+
总而言之,执行步骤1)一次创建视图,然后在每次需要执行计算时执行步骤3)。
我敢打赌,有一种更有效的方法 - 这不是我的强项。
我认为执行join
比将where
子句全部移动更便宜,创建视图只是一次性成本。