select min(date) 一组值

select min(date) for set of values

如何 select 像这样的一组值的最小(日期)table:

    date               status       failure_time
-------------------------------------------------
 2022-03-22 17:58:03     1             NULL
 2022-03-22 18:00:03     0             NULL
 2022-03-22 18:02:03     0             NULL
 2022-03-22 18:04:03     1              6
 2022-03-22 18:06:03     1             NULL
 2022-03-22 18:08:03     0             NULL
 2022-03-22 18:10:03     1              2

我尝试使用这个触发器:

    DECLARE LAST_STATUS integer;
    DECLARE LAST_DATE datetime;
    SET @LAST_STATUS := (SELECT `status` from crm ORDER by id DESC limit 1);
    SET @LAST_DATE   := (SELECT `date` from crm ORDER by id DESC limit 1);

    IF (NEW.status = 1 and  @LAST_STATUS = 0 ) THEN
        SET NEW.`failure_time` := TIMESTAMPDIFF(MINUTE, @LAST_DATE , NEW.date) ;
    END IF;

得到如下结果:

    date               status       failure_time
-------------------------------------------------
 2022-03-22 17:58:03     1             NULL
 2022-03-22 18:00:03     0             NULL
 2022-03-22 18:02:03     0             NULL
 2022-03-22 18:04:03     1              2
 2022-03-22 18:06:03     1             NULL
 2022-03-22 18:08:03     0             NULL
 2022-03-22 18:10:03     1              2

我的猜测是创建一个 table 作为标志和触发器,当有新的 'zero' 我将在 table 中插入日期,但我没有不需要解决这个问题。

我知道我需要在 'one' 之前获得第一个 'zero' 的日期,但我不知道如何。

在 MySQL 中,您 DECLARE 的变量没有 @ 标记,它们是局部变量,作用域为您在其中声明它们的触发器或过程。带有 @ 标记的变量不必声明(实际上,如果您尝试,这是一个错误),并且它们的范围仅限于会话。所以他们是完全不同的。许多人对 MySQL 感到困惑,因为在其他一些 SQL 产品中(咳咳,微软),变量的语法是不同的。

我还建议使用 INTO 语法,这样您就不必执行两次 SELECT 查询。

DECLARE LAST_STATUS INT;
DECLARE LAST_DATE DATETIME;

SELECT status, date INTO LAST_STATUS, LAST_DATE 
FROM crm ORDER BY id DESC LIMIT 1;

IF (NEW.status = 1 and  LAST_STATUS = 0 ) THEN
    SET NEW.`failure_time` = TIMESTAMPDIFF(MINUTE, LAST_DATE , NEW.date) ;
END IF;

:= 运算符在 SET 语句中使用时应写成 =:= 版本用于在表达式中作为 side-effect 进行赋值。

我通过反复阅读我的问题得到了结果,

DECLARE LAST_STATUS         INT;
DECLARE LAST_ONE_ID         INT;
DECLARE FIRST_ZERO_DATE     DATETIME;

select max(id) INTO LAST_ONE_ID from crm where status = 1 order by date desc;
select status INTO LAST_STATUS FROM crm ORDER BY id DESC LIMIT 1;
SELECT `date` INTO FIRST_ZERO_DATE from crm where id = ( LAST_ONE_ID + 1 ) ORDER by id DESC limit 1;

IF (NEW.status = 1 and  LAST_STATUS = 0 ) THEN
    SET NEW.`failure_time` := TIMESTAMPDIFF(SECOND, FIRST_ZERO_DATE , NEW.date) ;
END IF;

我用秒来测试,结果如下:

感谢@Bill Karwin 和@barmar 的帮助。

另外我认为对之前的查询有一些改进。