1

PHP では、複数の SQL テーブルからタイムスタンプのリストを取得し、一意のタイムスタンプをリストする配列を作成しています。ただし、タイムスタンプはテーブル間で同一ではなく、同じイベントでも 1 秒ほど異なる場合があります。したがって、たとえば、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

PHP で結果を処理する代わりに、クエリを編集することもできます。

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

これらの手順により、処理時間を大幅に短縮できますが、予想よりも少し余分な労力がかかる可能性があります.

仮定して :

  1. 変数 $qry には、結果を変数 $q に格納するクエリが含まれます
  2. 以下のように3つのテーブルがあります
  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 は、現在の行が table_1、table_2、または table_3 を参照していることを示す varchar です。フィールド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 を取得し、関連する行に更新することができます。このステップは 1 回だけ実行する必要があります。

次のステップは、クエリを変更してイベントを取得することです。これは例です:

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 に答える