2009-08-15 26 views
2

は、私は次のようになり、レコードを持つテーブルを持っている:SQL日付範囲に一致するレコード数のクエリ?

CREATE TABLE sample (
    ix int unsigned auto_increment primary key, 
    start_active datetime, 
    last_active datetime 
); 

私は多くのレコードは、過去30日間のそれぞれにアクティブであったかを知る必要があります。日はまた、最も古いものから最も新しいものに戻されるようにインクリメントされるべきである。

私はMySQLを使用しており、クエリはPHPから実行されますが、PHPコードは必要ありません。クエリだけです。ここで

は私のスタートだ:

SELECT COUNT(1) cnt, DATE(?each of last 30 days?) adate 
FROM sample 
WHERE adate BETWEEN start_active AND last_active 
GROUP BY adate; 

答えて

5

外部結合を行います。

表はありません?テーブルを作る。私はいつもこれのためにダミーのテーブルをつけています。

create table artificial_range( 
    id int not null primary key auto_increment, 
    name varchar(20) null) ; 

-- or whatever your database requires for an auto increment column 

insert into artificial_range(name) values (null) 
-- create one row. 

insert into artificial_range(name) select name from artificial_range; 
-- you now have two rows 

insert into artificial_range(name) select name from artificial_range; 
-- you now have four rows 

insert into artificial_range(name) select name from artificial_range; 
-- you now have eight rows 

--etc. 

insert into artificial_range(name) select name from artificial_range; 
-- you now have 1024 rows, with ids 1-1024 

今使用することが便利に、そしてビューで、30日にそれを制限する:

編集:JR Lawhorneノート:

あなたが「へ "DATE_ADD" に変更する必要がありますdate_sub "を使用して、作成したビューで前の30日間を取得します。

ありがとうございますJR!

編集:私は他の道に参加する必要があります。

create view each_of_the_last_30_days as 
select date_sub(now(), interval (id - 1) day) as adate 
from artificial_range where id < 32; 

今(私は実際にあなたクエリをテストしていない、私はちょうどそれが正常に動作すると仮定しています)クエリでこれを使用します

SELECT COUNT(*) cnt, b.adate 
FROM each_of_the_last_30_days b 
left outer join sample a 
on (b.adate BETWEEN a.start_active AND a.last_active) 
GROUP BY b.adate; 
+0

作成したビューで過去30日間を取得するには、「date_add」を「date_sub」に変更する必要があります。 –

0

SQLはデータベースに格納された値の一致セットで素晴らしいですが、それはがでないことを値の一致セットでそれほど大きくありませんデータベース。だから、1つの簡単な回避策は、あなたが必要とする値を含む一時テーブルを作成することです:

CREATE TEMPORARY TABLE days_ago (d SMALLINT); 
INSERT INTO days_ago (d) VALUES 
    (0), (1), (2), ... (29), (30); 

今、あなたはstart_activeと、各行のlast_active間のスパンにd日前の日付を比較することができます。グループ内で値がdの一致する行の数を数え、カウントを取得してください。

SELECT CURRENT_DATE - d DAYS, COUNT(*) cnt, 
FROM days_ago 
LEFT JOIN sample ON (CURRENT_DATE - d DAYS BETWEEN start_active AND last_active) 
GROUP BY d 
ORDER BY d DESC; -- oldest to newest 

別のノート:あなたはGROUP BY句に到達するまで、あなたは、式の中で、あなたの選択リストで定義された列の別名を使用することはできません。実際には、標準SQLではORDER BY節までは使用できませんが、MySQLではGROUP BYHAVING節に別名を使用することもサポートしています。

0
はあなたのクエリで、秒であるUNIXタイムスタンプ、に日付を回して、差が< =月の秒数であるためにそしてちょうど見

あなたがここでより多くの情報を見つけることができます:あなたは、クエリのヘルプが必要な場合は http://dev.mysql.com/doc/refman/5.1/en/date-and-time-functions.html#function_unix-timestamp

を私に知らせますが、MySQLは日時を扱うための素晴らしい機能を持っていてください。

[編集]私は本当の質問について混乱していたので、私は芝生を終わらせる必要がありますが、忘れる前にこれを書き留めたいと思います。

where句を上記のようにして過去30日間に制限したい場合は、1日のカウントを取得するには、1日ごとにグループ化する必要があります。月の日にして、それらのカウントを行います。

これは、開始日と終了日が数日に及ぶ場合、それぞれの使用が1日に制限されることを前提としています。

+0

どの日付をUNIXのタイムスタンプにするか? 'CURRENT_DATE - INTERVAL 30 DAY'、' start_active'または 'end_active'ですか?これは、OPグループの過去30日間の毎日の活動記録*のカウントをどのように助けますか? – pilcrow

+0

start_activeとlast_activeの両方をunix_timestampにするか、これを試したわけではありませんが、subtime()を使って時間を差し引いて変換するか、上記のページで次のようなものを使用できます:select ID MESSAGEからSENT_TIME <(CURDATE() - INTERVAL 5 DAY); それにもかかわらず、時間関数を見てみると、あなたのために最適なものを見つけることができるはずです。 –

+0

@James Black、あなたの答えのフレーズは、OPが30日の時間枠と重なっているレコードの数を知りたいと思っていると思いますが、それは間違った質問です。過去30日間(そうです、日付の算術演算はSQLのネイティブタイプや整数エポックスタンプでは簡単です)あなたの提案を説明するコードソリューションを投稿することはできますか? – pilcrow

関連する問題