我有一个状态机,状态机从状态1(真)开始,可以移动到状态2(暂时为假),从状态为假,它可以移回到状态1或状态3(假)。状态3可以自行循环或进入状态1。
如果状态从状态2进入状态3,则状态机从进入状态2到返回状态1(从状态3)到现在是false
。但是,如果它从状态2回到状态1,则它永远不会处于false
状态。
我将转换记录在数据库中,所以看起来像:
+----+------------------+---------------+-----------+---------------+---------------------+
| id | state_machine_id | current_state | new_state | last_event_id | ts |
+----+------------------+---------------+-----------+---------------+---------------------+
| 1 | 1 | 0 | 1 | NULL | 2018-12-26 16:18:51 |
| 2 | 1 | 1 | 2 | 1 | 2018-12-26 18:21:01 |
| 3 | 1 | 2 | 1 | 2 | 2018-12-26 18:35:24 |
| 4 | 1 | 1 | 2 | 3 | 2018-12-26 18:51:01 |
| 5 | 1 | 2 | 1 | 4 | 2018-12-26 18:51:42 |
| 6 | 1 | 1 | 2 | 5 | 2018-12-27 20:03:01 |
| 7 | 2 | 0 | 1 | NULL | 2018-12-28 02:07:49 |
| 8 | 1 | 2 | 3 | 6 | 2018-12-28 02:15:01 |
+----+------------------+---------------+-----------+---------------+---------------------+
状态0是起始状态的占位符,最后一个last_event_id
指的是特定状态机的最后一个事件。
问题:
接收startDate,endDate和state_machine_id
返回2D数组,其中每个元素都有一个日期以及状态机在那天是否为假。
示例:
输入:开始='2018-12-26',结束='2018-12-30',stateMachine = 1
输出:
+------------+-----------+
| day | is_false |
+------------+-----------+
| 2018-12-26 | 0 |
| 2018-12-27 | 0 |
| 2018-12-28 | 1 |
| 2018-12-29 | 1 |
| 2018-12-30 | 1 |
+------------+-----------+
我已通过编程方式完成了上述操作,以下是我的伪代码:
transitionsInSpan = db->run('SELECT * FROM transitions where ts >= $start and ts <= $end and state_machine_id = $stateMachine')->all()
if transitionsInSpan empty: //edge cases
$closestToStart = db->run('SELECT current_state, new_state from transitions WHERE state_machine_id = $stateMachine AND ts < $start ORDER BY ts DESC LIMIT 1')->first()
if(current_state = 2 and new_state = 3):
return dates with all true
else if(new_state = 2):
get the closestToEnd ... all true if new_state = 3
return false for all dates
else:
listOfDates = dates between start and end dates (inclusive)
iterate through listOfDates:
...this gets kind of messy and convoluted
我现在正在尝试使用mysql:
SELECT MAX(
IF
(
new_state = 3,
true,
IF
(
id IN
(
SELECT last_event_id from transitions WHERE new_state = 3
), true, false
)
)
) as is_false,
date(ts) as ts
FROM transitions
WHERE state_machine_id = 1
GROUP BY ts;
以上结果如下:
+-----------+------------+
| is_false | ts |
+-----------+------------+
| 0 | 2018-12-26 |
| 1 | 2018-12-27 |
| 1 | 2018-12-28 |
+-----------+------------+
但是我仍然需要用正确的日期和布尔值(即包含12-29和12-30作为正确的值)填充结尾,而且我不确定如何捕获介于两者之间的日期...