2010-11-30 4 views
18

間の平均間隔は、このテーブルを想定:のMySQL:レコードの

id date 
---------------- 
1  2010-12-12 
2  2010-12-13 
3  2010-12-18 
4  2010-12-22 
5  2010-12-23 

私はMySQLはクエリのみ使用し、これらの日付の間の平均間隔を見つけるにはどうすればよいですか?

例えば、このテーブル上の計算では、あなたが自分が参加し、DATEDIFF関数を使用して差分を取得し、平均取得行う必要がある

(
    (2010-12-13 - 2010-12-12) 
    + (2010-12-18 - 2010-12-13) 
    + (2010-12-22 - 2010-12-18) 
    + (2010-12-23 - 2010-12-22) 
)/4 
---------------------------------- 
= (1 DAY + 5 DAY + 4 DAY + 1 DAY)/4 
= 2.75 DAY 
+2

これはSQLで実行しなくても非常に簡単です。なぜそれをSQLで行う必要がありますか? – jwueller

+1

それは楽しいことのように聞こえるので。私はすでに私のPHP関数でこれを実装しました。しかし、私はそれが重要なパフォーマンスヒットなしにMySQLで行うことができるかどうかを知りたいのです。 – HyderA

+0

まず、2行の間のdiffを計算する必要があります:http://stackoverflow.com/questions/3017468 –

答えて

35

直感的に、何を求めていることは、私はより徹底的に説明しましょう日数マイナス

1で割った最初と最後の日付の間の間隔に相当する必要があります。日付はポイントがライン上にある想像(+が存在日付があり、-が欠落している日付は、最初の日付は12日で、私は、例示の目的のために12月24日に最後の日付を変更):

++----+---+-+ 

今、何あなたが本当にやりたい、あなたの日付は、これらの線の間のうち、均等空間であり、それが彼らのそれぞれの間でどのくらい見つける:

+--+--+--+--+ 

行うには、単に最初の最後との間の日数がかかる、ということこの場合は24 - 12 = 12とし、間隔を空けなければならない間隔の数で除算します。この場合、4:12/4 = 3

MySQLのクエリで

SELECT DATEDIFF(MAX(dt), MIN(dt))/(COUNT(dt) - 1) FROM a; 

これは、自分の価値観と、それは2を返します(このテーブルの上に動作します。75):

CREATE TABLE IF NOT EXISTS `a` (
    `dt` date NOT NULL 
) ENGINE=MyISAM DEFAULT CHARSET=latin1; 

INSERT INTO `a` (`dt`) VALUES 
('2010-12-12'), 
('2010-12-13'), 
('2010-12-18'), 
('2010-12-22'), 
('2010-12-24'); 
+2

D'oh、そうだよ!タイムスタンプしかなく、開始/終了ペアでない場合は、集約の嫌悪感は必要ありません。 – Dmitri

+4

+1パターンに従わず、実際に何が問題になっているかを見てください。 :D – Unreason

+1

あなたは先生、天才です!このソリューションは、ボックスの外で考えてシンプルさを実現する完璧な例です。 – HyderA

0

になります。

+0

テーブルに主キーがありません。だから、私が自己結合すると、次の行や前の行を使って計算するにはどうすればいいですか? – HyderA

+0

ユニークなフィールドはありませんか?内側のクエリを使用 –

+0

Yup!私に尋ねないで、私はそれをデザインしなかった。 – HyderA

2

IDが均一に、隙間なくインクリメントID + 1上の自身にテーブルを結合している場合:

SELECT d.id, d.date, n.date, datediff(d.date, n.date) 
FROM dates d 
JOIN dates n ON(n.id = d.id + 1) 

そしてGROUP BY、必要に応じて平均。

idsが均一でない場合は、内側のクエリを使用して順序付きIDを最初に割り当てます。

サブクエリを追加して合計行数を取得する必要があると思います。

また

以前の日付を追跡し、集計関数、および実行中の合計カウントを作成します。あなたは依然としてサブクエリから日付順の選択を行う必要があります(実際にはMySQLで保証されているかどうかはわかりません)。

これを考えてみると、これははるかに良い方法です。

そしてさらに簡単にするだけベガードのソリューションは、はるかに優れていることは注目に

+0

代わりに良いスタートですが、私は何が思いつくのか見てみましょう。 – HyderA

1

次のクエリは

SELECT AVG(
     DATEDIFF(i.date, (SELECT MAX(date) 
          FROM intervals WHERE date < i.date) 
       ) 
      ) 
FROM intervals i 

正しい結果を返しますが、それはありません、インデックスとし、多数の行に本当に非効率的であるかもしれない依存サブクエリを実行します。

+1

非常に非効率的で、100レコードを実行するのに約2秒かかりました。しかし、それはまさにそれが想定されているものです。これを最適化できますか? – HyderA

+0

そこでは幅のサブクエリがありますが、私はいつもゆっくりと問題になるでしょう。 –

関連する問題