快速使用数组的最近元素来确定新元素是否唯一

时间:2013-07-22 22:27:16

标签: php mysql

在PHP中,我从多个SQL表中获取时间戳列表,并创建一个列出唯一时间戳的数组。但是,不同表格之间的时间戳并不相同,并且对于同一事件,时间戳可能会相差一秒。因此,例如,我希望1374531523.343和1374531524.012被视为同一事件,但不是1374531520.342。

我一直在使用此功能来抓住与最近事件分开的时间:

function findNearest($number, $array, $index = false) {
    $min = abs($number - $array[0]);
    $min_i = 0;
    foreach ($array as $ind => $value) {    
        $mint = abs($number - $value);
        if ($mint < $min) {
            $min = $mint;
            $min_i = $ind;  
        }
    }   
    return ($index ? $min_i : $min);
}

(添加索引部分是因为有时候我需要最近时间的索引,但是这可以移到一个单独的函数中)

所以基本上我为每个表运行一个简单的SELECT ...查询并检查每个时间戳:

while ($g = $q->fetch_object())
    if (findNearest($g->timestamp, $timestamps) > 1) $timestamps[] = $g->timestamp;
}

这就像我想要的那样,但我正在查看大约100,000个不同的时间戳,并且将来会看到多达500,000个。随着$timestamps变得越来越大,这变得越来越慢。我知道这是不可避免的,但也许有更好的方法可以通过MySQL或PHP缩短时间?

3 个答案:

答案 0 :(得分:0)

是否可以为时间戳创建另一个MySQL表,并且可以创建一个id:

表:时间戳

time_id | timestamp
--------+---------------
1       | 1374531523.343

然后使用id与使用相同时间戳的所有其他表相关联:

其他表:

table_id | timestamps_time_id | etc...
---------+--------------------+-------
1        | 1                  | etc...

答案 1 :(得分:0)

也许您可以编辑查询而不是使用PHP处理结果:

SELECT time FROM table GROUP BY time DIV 1

答案 2 :(得分:0)

这些步骤可以更快地缩短处理时间,但可能会花费你额外的工作量。

假设:

  1. 变量$ qry包含将结果存储到变量$ q
  2. 的查询
  3. 您有三个表格如下
  4. 你做的查询,在你的例子中由$ q使用,从table_1,table_2开始,最后是table_3
  5. 表table_1:

    id | col_timestamp | parent_table | parent_id
    ---------------------------------------------
     1 | 1374531523.343|         NULL |      NULL
    

    表table_2:

    id | col_timestamp | parent_table | parent_id
    ---------------------------------------------
     1 | 1374531520.444|         NULL |      NULL
     2 | 1374531524.012|      table_1 |         1
     3 | 1374531556.012|         NULL |         1
     4 | 1374531556.512|      table_2 |         3
    

    表table_3:

    id | col_timestamp | parent_table | parent_id
    ---------------------------------------------
     1 | 1374531521.111|      table_2 |         1
     2 | 1374531523.111|      table_1 |         1
    

    说明:字段parent_table是一个varchar,表示当前行引用table_1,table_2或table_3。字段parent_id引用字段parent_table指向的表中的字段id。

    现在,每次用户插入所有表时,我们都需要检查数据库中是否已存在类似事件。我们可以通过使用触发器来实现。每次向table_2插入一行时都会触发此触发器:

    DELIMITER $$
    
    USE `your_database`$$
    
    DROP TRIGGER /*!50032 IF EXISTS */ `before_insert_table_2`$$
    
    CREATE TRIGGER `before_insert_table_2` BEFORE INSERT 
    ON `table_2` FOR EACH ROW 
    BEGIN
      DECLARE var_id INTEGER ;
      DECLARE var_table VARCHAR (10) ;
      SELECT id, parent_table INTO var_id, var_table 
      FROM
        ( SELECT id, 'table_1' AS parent_table, col_timestamp 
          FROM table_1 
          WHERE parent_id IS NULL 
          AND col_timestamp BETWEEN NEW.col_timestamp - 1 AND NEW.col_timestamp + 1 
          UNION
          SELECT id, 'table_2' AS parent_table, col_timestamp 
          FROM table_2 
          WHERE parent_id IS NULL 
          AND col_timestamp BETWEEN NEW.col_timestamp - 1 AND NEW.col_timestamp + 1
        ) 
      ORDER BY ABS(col_timestamp - NEW.col_timestamp), parent_table 
      LIMIT 1 ;
      SET NEW.parent_id = var_id ;
      SET NEW.parent_table = var_table ;
    END ;
    $$
    
    DELIMITER ;
    

    执行与table_1和table_3类似的步骤。

    下一步是将parent_table和parent_id设置为已存在的数据。您可以修改$ qry以获取表名及其ID并更新到关联的行。此步骤只需运行一次。

    下一步是修改您的查询以获取事件。这是一个例子:

    SELECT 'table_1' original_table, id
    FROM table_1 
    WHERE parent_id IS NULL
    UNION
    SELECT 'table_2' original_table, id
    FROM table_2
    WHERE parent_id IS NULL
    UNION
    SELECT 'table_3' original_table, id
    FROM table_3
    WHERE parent_id IS NULL
    

    最后一步是修改程序以实现数据库中的更改。

    希望这有帮助。