2012-02-09 7 views
0

MySQL:日付範囲を持つデータの月に1行を作成

私は、日付範囲の値を含むテーブル(mySQL 5.0.x)を持っています。

  • IDレコード
  • LINK_IDのIDが他のテーブルに
  • TYPE_IDデータをリンクするための値のタイプを決定するためである
    | id | link_id | type_id | value | start | end | 
    ==================================================== 
    | 1 |  1 |  1 | 10 | 201111 | 201202 | 
    | 2 |  1 |  2 | 20 | 201110 | 201201 | 
    | 3 |  1 |  1 | 100 | 201202 | 201202 | 
    | 4 |  2 |  1 | 40 | 201202 | 201203 | 
    

    他のテーブルから

  • 開始終了範囲(年と月の実際の日付または整数)を定義する数値
  • ある

トリックは、私がのタイプとリンクあたり合計値を提示する必要があるということです毎月の所定の期間。私はデータベースにこのような情報を入れるためにPHPを使用することができますが、いくつかの欠点がある

| period | link_id | type_id | value | 
====================================== 
| 201201 |  1 |  1 | 10 | 
| 201202 |  1 |  1 | 110 | 
| 201201 |  1 |  2 | 20 | 
| 201201 |  2 | NULL | NULL | 
| 201202 |  2 |  1 | 40 | 

:201202 - だから、結果が範囲201201のために、このようにする必要があります。私は何百ものlink_ids、多くのtype_idを持っており、開始日と終了日の平均の差は30ヶ月なので、たくさんの行があります。

+0

開始日と終了日の保存方法は、DATEフィールドですか? – vulkanino

+0

それは解決策によって異なります。何らかの種類の日付または6桁の整数にすることができます。いくつかのmysql _PERIOD_関数のために6桁の整数を使用しましたが、必須ではありません。 – Peter

答えて

0

これを行う方法が1つあります。 。私は(私はこれを簡略化することができ、このやっかいな気持ちを持っているが、それはcurrenty私をエスケープ)ので、あなたは彼らが遊ぶ方法を確認することができます$startMonth$endMonthに入れている:

SET @MONTH:=$startMonth-1; 

SELECT month, link_id, type_id, SUM(value) AS value 
FROM (SELECT @MONTH:[email protected]+1 as month 
     FROM foo f 
     LIMIT $endMonth-$startMonth+1) a 
LEFT JOIN foo f 
ON a.month >= f.start AND a.month <= f.end 
GROUP BY link_id, type_id, a.month; 

それが動作する方法:あなたが持っていたと仮定します表a

+-------+ 
| month | 
+-------+ 
|201201 | 
|201202 | 
+-------+ 

次にあなたが後にしているクエリが動作するようにずっと簡単です:

SELECT month, link_id, type_id, SUM(value) AS value 
FROM a 
LEFT JOIN foo 
ON a.month >= f.start AND a.month <= f.end 
GROUP BY link_id, type_id, a.month; 

すなわち、あなたはテーブルに参加します3210からfooまでの数字をmonthに設定し、開始日と終了日の間に値を設定し、月、リンクID、およびタイプIDでグループ化するだけです。

したがって、$startMonthから$endMonthまでの数字を含むテーブルaをどのように生成するかが問題です。したがって:

SET @MONTH:=201200; 
SELECT @MONTH:[email protected]+1 AS month 
FROM foo 
LIMIT 2; 

これは201201からとIE 201202までの2行、とstartign番号のテーブルを提供します。このクエリでは、FROM fooはダミーです - 実際には使用されません。

+0

ありがとう!ほぼ完璧です。2つの問題(1つは私のものです)。 1)2011年以降、201201の代わりに201113が次の値になりますが、事前に作成されたテーブルで処理できます。 2)指定した期間の値を持たない月のNULL値を持つ必要があるとは言いませんでした。 (**私は質問を修正しました!**) – Peter

+0

'SELECT @MONTH:= @ MONTH + 1 AS month'は正確な操作のために' SELECT @MONTH:= PERIOD_ADD(@MONTH、1)AS month'と ' foo'には、少なくとも開始日と終了日の間の違いと同じくらい多くの行が必要です。 – Peter

+0

ああ、私は周りのラッピングの何かを忘れていることを知っていた。 'foo'の良い点は、少なくとも多くの行が必要です。私はこれを行う別の方法が必要であると思います。 (どうしてなぜMySQLに「xxxとyyの間でSELECT INTがあるのですか」というのはありませんか?) –

関連する問題