根据MySQL/MariaDB中的时间戳选择N个大致等距的行

3okqufwl  于 2022-11-08  发布在  Mysql
关注(0)|答案(1)|浏览(125)

这个问题被问到earlier,但是从讨论中看,这个问题没有足够的输入来确定输出。我有一个类似的问题。我将尝试提出一些规范/逻辑。
我有一个包含时间戳数据的表,我已经将它转换为unix_timestamp。
| 标识符|p值|ceil(unix时间戳(更新时间))|
| - -|- -|- -|
| 三个|三百个|小行星1653549602|
| 七个|三百个|小行星1653549902|
| 十一|三百个|小行星1653550|
| 十五个|三百个|小行星1653550502|
| 十九个|三百个|小行星1653550802|
| 二十三个|一千二百|小行星1653551102|
| 二十七人|一千三百|小行星1653551402|
| 三十一个|一千三百|小行星1653551402|
| 三十五个|一千三百|小行星1653551702|
| 三十九|一千三百|小行星1653551702|
这是10行,时间大致相等。假设我想要N大致相等的行。那么我对N = 3执行以下步骤,
1.将集合除以N - 1,即(max - min)/(N - 1),得到2100/2 = 1050
1.选择第一行(时间戳为1653549602)另存为最后一行
1.然后选取(具有updated_at〉(last + 1050)的第一行),即具有时间戳1653550802,并保存为last。
1.重复步骤3,直到它超过max;使用最大值作为最后一个样本,即时间戳为1653551702。
我有一个粗略的算法,但是如何用SQL写这个。

示例输出:

| 标识符|p值|ceil(unix时间戳(更新时间))|
| - -|- -|- -|
| 三个|三百个|小行星1653549602|
| 十九个|三百个|小行星1653550802|
| 三十九|一千三百|小行星1653551702|

i1icjdpr

i1icjdpr1#

我只是试了一下。检查一下这个可以帮助你。就试试我给出的函数。
1.您的'1653549602'不是最后一条记录。它是保存到表中的第一条记录。
1653549602 = 2022-05-26 07:20:02〈--第一条记录7:20
和1653551702 = 2022-05-26 07:55:02.〈--最后一条记录在7:55.
1.另外,我觉得在选择最后一条记录时,您描述的场景存在逻辑问题。因为1653550802 + 1050表示实时时间为--〉“2022-05-26 07:57:32”。所以您不能通过此条件选择“1653551702”作为记录updated_at〉(last + 1050))。1653551702 =“2022-05-26 07:55:02”。因此您的条件不适用于此条件。
1653550802 + 1050 = 1653551852,即“2022-05-26 07:57:32”,因此该条件不起作用[“2022-05-26 07:55:02”〉“2022-05-26 07:57:32”]

[从这里开始]

无论如何,我为你做了一个程序。它给你一个一些想法,你的要求,也将帮助你前进。
我使用的表结构与

create table `equidistants` (
    `pid` int (11),
    `id` int (11),
    `p_value` int (11),
    `unix_time` bigint (20)
);

pid是我创建的作为PK的列
使用的表名:等距离线
1.创建日期低于函数

DROP PROCEDURE IF EXISTS my_proc_equidistant;

  DELIMITER $$

  CREATE PROCEDURE my_proc_equidistant(IN n_value INT)
  BEGIN

     DECLARE i_val INT; -- Variable for (max - min)/(N - 1)
     DECLARE i_loop INT DEFAULT 0;
     DECLARE i_Selected_unixTime INT;

     SET n_value = n_value -1;

     -- Handle the devided by 0 error
     IF n_value = 0 THEN 
         SET n_value = 1 ;
     END IF;

     -- (max - min)/(N - 1) calculate here
     SELECT  (MAX(unix_time) - MIN(unix_time))/(n_value) 
     INTO i_val FROM `equidistants` ; 

     -- Get the first updated value. Not the last one  
     SELECT unix_time INTO i_Selected_unixTime 
     FROM `equidistants`  ORDER BY unix_time ASC LIMIT 1; 

     -- Temporary table to keep your Data
     DROP TABLE IF EXISTS temp_equidistants; 

     -- Inser the latest record from the data set.
     CREATE TEMPORARY TABLE temp_equidistants  
     SELECT * FROM equidistants  ORDER BY unix_time ASC LIMIT 1;

      -- Start the loop based on the given N value
      WHILE i_loop < n_value DO

         -- Insert the next selected record into the temp table base on the [last selected unix time + i_val]   
         INSERT INTO temp_equidistants 
         SELECT  *  FROM equidistants WHERE unix_time > i_Selected_unixTime + i_val  ORDER BY  unix_time ASC LIMIT 1;

         -- identify the next unix time 
         SELECT  unix_time INTO i_Selected_unixTime FROM equidistants WHERE unix_time > i_Selected_unixTime + i_val  ORDER BY  unix_time ASC LIMIT 1;

         SET i_loop=i_loop+1;
       END WHILE;

       -- Execute the result you need
       SELECT * FROM temp_equidistants; 

       -- Drop the Temp table
       DROP TABLE IF EXISTS temp_equidistants; 

  END$$

  DELIMITER ;

希望你可以通过修改一些区域来做一些事情。
1.结果我得到了x1c 0d1x
注:由于我在顶部解释的条件不匹配,第3条记录缺失
这里我用了“ASC”作为order by子句。你可以把它改为降序,也可以用其他方式运行它。

相关问题