2011-06-28 7 views
2


気象データを表示するjqueryベースのWebグラフを作成しています。データはAjax - > PHP - > MySQL経由でロードされます。 MySQLデータベースには、過去10年間の1分ごとのさまざまなパラメータのレコードが含まれています(膨大なレコード)。私は、ユーザーがカスタムの日付範囲のグラフを生成できるようにしたいが、データ範囲の数を数日以上に制限する。つまり、1週間分のデータを照会すると、PHPコードでは1時間あたり1つのデータ値しか返されません。
平均化やサーバー側の処理をしたくない - mysqlからn番目のレコードのみを取得したい - 管理可能な量のデータが得られるようにする。MySQLクエリの日付ベースのn番目のレコード

私の問題は、データベースにレコード番号フィールドがなく、データベースのフォーマットを変更できないということです。実際の日付の値に基づいてこれを実行できる方法はありますか? unixタイムスタンプへのキャストと同様に、日付がある数値で割り切れる場合はレコードを選択するだけですか? (私は、一定の数のポイントを引き出すために、時間範囲の長さに基づいて数を計算する)

これを行うには良い方法はありますか?時間間隔を均等に選択できる解決策があれば理想的です。 (つまり、5分、10分、1時間、5時間など)

EDIT:フィールドはMySQLのdateTime形式です!説明を求めてくれてありがとう!句

SELECT * FROM WEATHER WHERE MOD(UNIX_TIMESTAMP(Time), Divisor) = 0

は除数で割り切れる回あなたレコードだけを取得するWHERE

+0

データベースに格納されている時間はどの形式ですか(mysql datetime列かunix timestamp列か)。その列は索引付けされていますか? – Arjan

+0

テーブルの詳細を追加できますか? –

+0

申し訳ありませんコメントありがとう。これはMySQLのdatetimeカラムです! –

答えて

1

はあなたのSQLにMOD()UNIX_TIMESTAMP()機能を使用することができます。除数は、データを取得する時間の増分(5分ごとに300、1.5時間ごとに5400など)となります。

UNIX Timeは32ビット整数を使用するため、MySQLの標準INTデータ型は正常です。

+1

クエリが長い間隔(例:5年)で使用されている場合、このクエリは十分に速くはありません。いずれにしても、データベースを変更しなくても良い解決策を見つけるのは難しいと思います。問題は、日時フィールドの計算は、このフィールドのインデックスがクエリで使用されないことを意味します。 – Karolis

+0

@Karolis答えを更新しました。 – Dirk

+0

いいですね。それは私が探していたものです。私は明日それを試してみて、報告して戻ってきます。ありがとう! :) –

0

DATETIMEをUNIXのタイムスタンプに変換し、必要な間隔(次の例では10分)で除算した後、GROUP BYを使用して異なる値ごとに1行に減らすことができます。

SELECT FLOOR(UNIX_TIMESTAMP(datetime_col)/600) AS ts, * FROM WEATHER 
WHERE datetime_col BETWEEN ? AND ? 
GROUP BY ts 

これは、インデックス付けされていない列としてすべての行に対してtsを計算し、そのことにより、グループする必要があるため、非常に高速であることを行っていません。

また、これはあいまいなGROUP BYクエリを許可するMySQLの非標準動作に依存します。つまり、ストレージエンジンによって決定されたグループから任意の行が戻されます。実際には、物理​​的に格納されている最初の行ですが、ストレージエンジンやインデックスなどを扱うと混乱する可能性があります。

代替:ユーザー変数を使用して行数をカウントし、間隔が変化する。

SET @interval := 0; 
SET @row := 0; 
SELECT t.* FROM (
SELECT (@i:=FLOOR(UNIX_TIMESTAMP(datetime_col)/600)), 
    IF(@interval<>@i),@row:=0,@row:[email protected]+1) AS row, @interval:[email protected], * 
FROM WEATHER 
WHERE datetime_col BETWEEN ? AND ? 
) AS t 
WHERE t.row = 0; 
0

同様に日付が、いくつかの数で割り切れるならば、レコードのみを選択し、UNIXタイムスタンプにキャスト言いますか?

この問題、およびほとんどのアプローチでは、(タイムスタンプのさまざまな表現を含むインデックス付きの列がない限り)連続するすべての点を読み取る必要があるため、結果セットのサイズを小さくする可能性がありますそれを抽出するのに必要な作業の量ではありません。

新しいテーブルを作成できますか(同じデータベース/サーバーにある必要はありません。フェデレーションエンジンを使用して未加工のデータに接続することはできます)。そのようにして、ハノイの塔の中で異なる粒度のタイムスタンプのテーブルを設定することができます。

date time  level 
------------- ----- 
201101010000 0 
201101010010 6 
201101010020 6 
201101010030 5 
201101010040 6 
201101010050 6 
201101010100 4 
201101010110 6 
201101010120 6 
201101010130 5 
... 
201101020000 3 
... 

このようにして、適切な粒度でこの話から選択し、基になるrawdataに結合することができます。

上記の方法は、データを集約するための機能として実装されていますが、参照することができません。から、srcデータのすべての行を読み込む必要があります。

私が直接でも時間間隔

何か上記のように

SELECT DATE_FORMAT(yourdate, SUBSTR('%Y%m%d%H%i%s',0,2*@level)) as t, 
AVG(value) 
FROM yourtable 
WHERE yourdate BETWEEN @datestart AND @dateend 
GROUP BY DATE_FORMAT(yourdate, SUBSTR('%Y%m%d%H%i%s',0,2*@level)) 
ORDER BY 1; 

(....のように選択することができるようになる解決策があった場合 - に参加する2番目のテーブルなしで索引を使用して再取得されたデータ・サンプルのみを選択する方法には、集約fnを使用する際のパフォーマンス上のペナルティはありません。

関連する問題