2009-08-20 15 views
6

私は、MySQLデータベースに、最も近いタイムスタンプを持つ行を別のタイムスタンプから選択したいテーブルを持っています。MySQLで最も近い整数を見つける最も効率的な方法は?

timeは、タイムスタンプ列(UNIXのUNIXタイムスタンプ)です。私は1250710000を任意に選んだ。

これは私が作ってみたクエリであり、それを行うには、より効率的な方法があります場合、私は思ったんだけど:

SELECT *, ABS(time - 1250710000) AS time_dist FROM table 
ORDER BY time_dist ASC LIMIT 1 

が、これはそれを行うための最善の方法ですか?

答えて

10

timeがインデックス化されたと仮定すると、あなたが自由のためにほぼのレコードを取得することができます:

SELECT * FROM table WHERE time > 1250710000 ORDER BY time LIMIT 1 

をそして、私は間違っていないよ場合は、同じことが前のレコードに適用されるべきである、MySQLはちょうど読みますインデックスを逆順に並べ替えます。 2つのUNIONを使って、日付と差分で順序を決めてください!その結果は、理想的には、この

SELECT * 
FROM 
(
    (SELECT *, ABS(time - 1250710000) AS time_diff FROM table WHERE time > 1250710000 ORDER BY time ASC LIMIT 1) 
    UNION ALL 
    (SELECT *, ABS(time - 1250710000) AS time_diff FROM table WHERE time < 1250710000 ORDER BY time DESC LIMIT 1) 
) AS tmp 
ORDER BY time_diff 
LIMIT 1 

のようになります。代わりに><のあなたは、同じタイムスタンプを共有するレコードを考慮して、>=<=を使用し、その主なIDを使用して参照レコードを除外する必要があります。

+0

くそー!私はほとんど正確にそれを入力していた! – NickZoic

+0

素晴らしいアイデアですが、参照タイムスタンプ(この場合は '1250710000')は同じテーブルにありません。 これは言いましたが、私はこのクエリが効率に関してほぼ同じであると仮定します。 – heyitsme

+0

** @ cyouung:**このクエリは、効率の面で同じではありません。あなたのクエリは、* 1行ごとに* ABS(時間 - 125071000)を行います*。 'time'にインデックスがある限り、このクエリは2つ以上の行を読み取ることはありません。 –

1

エヴァンが言ったように、あなたが持っている方法はうまくいきます。そのタイムスタンプフィールドにインデックスを付けることをお勧めします。これにより、MySQLはテーブル全体ではなく小さなインデックスをスキャンできます。また、私は、インデックスが物事をスピードアップすることができるかどうかを確認するためにいくつかの「ボクシング」をしようとするだろう:

SELECT *, ABS(time - 1250710000) AS time_dist FROM table 
WHERE time between(1250610000,1250810000) 
ORDER BY time_dist ASC LIMIT 1 

上記の制限を約+/- 1日に照会します。追加の索引スキャン(where句)が表のすべての項目についてABS()を計算するよりも高速かどうかを確認するために、いくつかのベンチマークを実行する必要があります。

+0

私はそのような任意の制限を嫌っています。 –

1

より大きい最小時間を選択する方が効率的でしょうか?そして、最大の時間はより短いですか? 時間はそれよりも小さく、その後はちょうどabsです。そのため、テーブル全体を操作する必要はありません( )。

SELECT MAX(時間)AS前の時刻< 1250710000;

SELECT MIN(時間)AS次の時間> 1250710000;

SELECT MIN(ABS(前)、ABS(次));

私のSQLはそれらを1つにまとめるには強くなく、3つの クエリのオーバーヘッドが節約を殺す可能性がありますが、可能性があります。

関連する問題