【问题标题】:Sql query to identify running previous row value and do some computationsSql 查询以识别运行的前一行值并进行一些计算
【发布时间】:2021-10-17 02:25:32
【问题描述】:

以下是包含original_datepriority 列的数据集。根据某些条件识别输出的查询。条件如下所述

逻辑:

如果之前和当前日期与原始日期列的差小于 4 分钟且优先级大于 2,则在原始日期上增加 4 分钟。

注意:这个新的输出日期将是下一行计算的前一个日期。

很难根据上述条件填充输出。

CREATE OR REPLACE TABLE test_sev
(
    original_date TIMESTAMP_NTZ(9),
    priority varchar
);

INSERT INTO test_sev VALUES ('7/29/2021 14:45:00', 2);
INSERT INTO test_sev VALUES ('7/29/2021 14:46:41', 3);
INSERT INTO test_sev VALUES ('7/29/2021 14:47:13', 4);
INSERT INTO test_sev VALUES ('7/29/2021 14:51:38', 3);
INSERT INTO test_sev VALUES ('7/29/2021 14:51:46', 4);
INSERT INTO test_sev VALUES ('7/29/2021 15:05:50', 1);
INSERT INTO test_sev VALUES ('7/29/2021 15:13:50', 4);

输入数据集:

使用的查询:

WITH DATA1 AS
(
    SELECT
        original_date,
        LAG(original_date, 1) OVER (ORDER BY original_date) AS prev_original_date,
        DATEDIFF('minute', prev_original_date, original_date) AS TIME_DIFF,
        CASE 
            WHEN priority > 2 AND TIME_DIFF < 4 
                THEN DATEADD ('minute', 4, prev_original_date) 
                ELSE original_date 
        END AS new_original_date,
        priority
    FROM 
        test_sev
)
SELECT
    original_date, priority, new_original_date 
FROM 
    DATA1;

我得到的输出:

问题:第 3、4 和 5 行错误。它没有从正在运行的new_original_date 获取上一个日期。

正确的输出:

请您帮忙解答一下正确的查询。感谢您对此的帮助。谢谢。

【问题讨论】:

  • 您的查询按照您想要的逻辑进行。你想要的输出没有意义。
  • 您真正使用的是哪个数据库?删除其他标签。

标签: mysql sql sql-server oracle


【解决方案1】:

更新了 MySQL 8.0 和 MariaDB 10.5 的 SQL

我猜不出你的数据库,也不支持你的CREATE TABLE 声明。

由于您标记了 MySQL,我决定只进行必要的更改以使用该数据库(和 MariaDB)运行。

您的 SQL 中的一个问题是标准,大多数数据库不支持访问同一 SELECT 列表中的派生列。通常,我们需要将表达式放在派生表或 CTE 术语中,然后在外部(或后续)查询表达式中引用派生列。

另一种方法是根据需要使用原始表达式而不是派生列名。

这是一个使用这种方法的 MySQL 8.0 和 MariaDB 10.5 中的 SQL 示例(更新为使用递归):

MySQL/MariaDB 的 SQL:

WITH RECURSIVE data1 ( original_date, priority, seq ) AS (
          SELECT t.*, ROW_NUMBER() OVER (ORDER BY original_date) FROM test_sev AS t
     )
   , data0 ( original_date, prev_original_date, priority, new_original_date, seq ) AS (
          SELECT original_date, CAST(null AS DATETIME), priority, original_date, seq FROM data1 WHERE seq = 1 UNION ALL
          SELECT d1.original_date
               , d0.new_original_date
               , d1.priority
               , CASE
                    WHEN d1.priority > 2
                     AND TIMESTAMPDIFF(minute, d0.new_original_date, d1.original_date) < 4
                    THEN d0.new_original_date + INTERVAL '4' MINUTE
                    ELSE d1.original_date
                 END AS new_orig
               , d1.seq
            FROM data1 AS d1
            JOIN data0 AS d0
              ON d1.seq = d0.seq+1
     )
SELECT * FROM data0
;

结果:

+---------------------+---------------------+----------+---------------------+------+
| original_date       | prev_original_date  | priority | new_original_date   | seq  |
+---------------------+---------------------+----------+---------------------+------+
| 2021-07-29 14:45:00 | NULL                | 2        | 2021-07-29 14:45:00 |    1 |
| 2021-07-29 14:46:41 | 2021-07-29 14:45:00 | 3        | 2021-07-29 14:49:00 |    2 |
| 2021-07-29 14:47:13 | 2021-07-29 14:49:00 | 4        | 2021-07-29 14:53:00 |    3 |
| 2021-07-29 14:51:38 | 2021-07-29 14:53:00 | 3        | 2021-07-29 14:57:00 |    4 |
| 2021-07-29 14:51:46 | 2021-07-29 14:57:00 | 4        | 2021-07-29 15:01:00 |    5 |
| 2021-07-29 15:05:50 | 2021-07-29 15:01:00 | 1        | 2021-07-29 15:05:50 |    6 |
| 2021-07-29 15:13:50 | 2021-07-29 15:05:50 | 4        | 2021-07-29 15:13:50 |    7 |
+---------------------+---------------------+----------+---------------------+------+

Working Test Case for MySQL and MariaDB

【讨论】:

  • 感谢 Jon 的尝试。这与我的查询得到的输出相同。如果您查看第 3,4 和 5 行,这是不正确的。实际值应该是上一个运行行 [new_orginal_date] 加上 4 分钟。
  • @Ansip 我想我误解了。你是说你想要一种“跑步调整”吗?这可以递归地完成。如果那是正确的,我马上就去试一试。
  • 是的,这是正确的,需要为此逻辑进行运行调整
  • @Ansip 查看我的更新答案。它使用递归 CTE 生成所需的结果。
  • @Ansip 您标记了 MySQL,所以我在答案中使用了 MySQL。如果您使用不同的数据库,可以根据需要进行调整。然而,你还没有回答这个问题。大多数主要数据库都支持这一点。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-01-10
  • 1970-01-01
  • 1970-01-01
  • 2021-10-27
  • 1970-01-01
  • 1970-01-01
  • 2021-10-04
相关资源
最近更新 更多