确定状态机处于状态的日子

时间:2019-01-04 20:37:48

标签: mysql state-machine

我有一个状态机,状态机从状态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作为正确的值)填充结尾,而且我不确定如何捕获介于两者之间的日期...

0 个答案:

没有答案