1

在 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?

4

3 回答 3

0

这些步骤可以更快地缩短您的处理时间,但可能会花费您比您预期的更多的努力。

假如说 :

  1. 变量 $qry 包含将结果存储到变量 $q 的查询
  2. 你有如下三个表
  3. 您进行查询,在您的示例中由 $q 使用,依次从 table_1、table_2 和最后 table_3 开始

表 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

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

希望这会有所帮助。

于 2013-07-23T01:15:22.273 回答
0

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

SELECT time FROM table GROUP BY time DIV 1
于 2013-07-22T22:37:44.447 回答
0

是否可以为时间戳和 id 创建另一个 MySQL 表,例如:

表:时间戳

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

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

其他表:

table_id | timestamps_time_id | etc...
---------+--------------------+-------
1        | 1                  | etc...
于 2013-07-22T22:34:56.000 回答