选择最小值(日期)作为一组值

发布于 2025-01-16 14:39:08 字数 1410 浏览 4 评论 0原文

如何为像这样的表这样的一组值选择分钟(日期):

    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

我的猜测是创建一个表,当有新的“零”时,它充当标志和触发器我将在该表中插入日期,但我不需要解决这个问题。

我知道我需要获取“一”之前的第一个“零”的日期,但我不知道如何。

How to select the min(date) for set of values like this 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

My try using this trigger :

    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;

Gave a result like:

    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

My guess is to create a table which works as a flag and a trigger, when there is new 'zero' I will insert the date inside that table, but I don't need that work around.

I know that I need to get the date of first 'zero' before 'one' but I don't know how.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

夏夜暖风 2025-01-23 14:39:08

在 MySQL 中,您声明的变量没有 @ 印记,它们是局部变量,其作用域为您在其中声明它们的触发器或过程。您没有使用 @ 印记的变量必须声明(事实上,如果你尝试的话,这是一个错误),并且它们的范围仅限于会话。所以他们是完全不同的。许多人对 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 语句中使用 := 运算符时,应将其写为 =。当您想要将赋值作为表达式中的副作用时,请使用 := 版本。

In MySQL, variables you DECLARE have no @ sigil, and they are local variables scoped to the trigger or procedure you declare them in. Variables with the @ sigil you don't have to declare (in fact it's an error if you try), and they have are scoped to the session. So they're completely different. Many people get confused with MySQL because in some other SQL products (ahem Microsoft), the syntax of variables is different.

I'd also recommend using INTO syntax, so you don't have to do the SELECT query twice.

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;

The := operator should be written as = when you use it in a SET statement. The := version is used when you want to do an assignment as a side-effect within an expression.

轮廓§ 2025-01-23 14:39:08

我通过一遍又一遍地阅读我的问题得到了结果,

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 的帮助。

我也认为之前的查询有一些改进。

I got the result by reading again and again my question,

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;

I use second for test, here's the result:

enter image description here

thanks to @Bill Karwin and @barmar for your help.

also I think that there is some improvement to the previous query.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文