人力検索はてな
モバイル版を表示しています。PC版はこちら
i-mobile

PHPとMySQLを使い、過去15日間のデータを表示できるようにしたいと思っています。

登録値がなかったとしても必ず過去15日間を表示する為に、forを使い、以下のようにしています。

for($i=0;$i<15;$i++){
$acc_day = date("Y-m-d",strtotime("-$i day"));
$sql = "SELECT date,count(acc) AS cnt FROM access WHERE date='$acc_day' GROUP BY acc";
$res = mysql_query($sql,$conn);
$acc = mysql_fetch_array($res);

echo $i.":";
echo number_format($acc[cnt])."<br>";
}

しかし、これだとforの度にクエリを発行しているので、そこが気になっています。

もっと簡略化した、データベースに負担のかからない書き方というのがあれば、教えて下さい。
PHPは5.1.20、MySQLは4.1.22を使用しています。

●質問者: kt26
●カテゴリ:ウェブ制作
✍キーワード:access as CNT echo GROUP
○ 状態 :終了
└ 回答数 : 3/3件

▽最新の回答へ

1 ● b-wind
●40ポイント
$day_map = array();
for($i=0;$i<15;$i++){
 $acc_day = date("Y-m-d",strtotime("-$i day"));
 $day_map[$acc_day] = 0;
}

$start_day = $day_map[0];
$end_day = $day_map[-1];
$sql = "SELECT DATE_FORMAT(date,'%Y-%m-%d') AS date, count(acc) AS cnt FROM access WHERE date BETWEEN '$start_day' AND '$end_day' GROUP BY acc";
$res = mysql_query($sql,$conn);
while ( $row = mysql_fetch_array($res) ) {
 $day = $row['day'];
 $count = $row['cnt'];
 $day_map[$day] += $count;
}

foreach ( $day_map as $date => $count ) [
 echo $date.":";
 echo number_format($count)."<br>";
}
}

試してないけど。

◎質問者からの返答

うーん、、、当初の希望である「簡略化した」という希望に沿わない気がします。。


とりあえず試して参考にします。ありがとうございました。


2 ● pahoo
●15ポイント

dateカラムは文字列型のようなので、下記のようにすればforループは不要になると思います。

$acc_day = date("Y-m-d",strtotime("-14 day"));
$sql = "SELECT date,count(acc) AS cnt FROM access WHERE strcmp(date,'$acc_day')>=0 GROUP BY acc";

実際には、strcmp関数の代わりに

date>='$acc_day'

で処理できるのですが、これが正規のやり方かどうかは分かりません。


参考サイト

◎質問者からの返答

dateなんで文字列ではなく日付型ですよ。


また、上記の方法で15日間のデータが出せるのでしょうか?試してみたのですが、何も出力されませんでした。


3 ● y-kawaz
●25ポイント

以下のようなSQLを投げればデータの無い日付はcntがゼロとして一発で取得できますが、求めているのはこういうことで合ってるでしょうか?

SELECT days.date, count(acc) AS cnt
FROM ( SELECT '2008-03-02' AS date
 UNION SELECT '2008-03-03'
 UNION SELECT '2008-03-04'
 UNION SELECT '2008-03-05'
 UNION SELECT '2008-03-06'
 UNION SELECT '2008-03-07'
 ) days
LEFT OUTER JOIN access ON days.date=access.date
GROUP BY access.acc
ORDER BY days.date, access.acc;
◎質問者からの返答

確かに、この方法だとデータの内日付でも表示できるのですが、

やはりUNIONしている箇所はforで取得するしかないですよね?

もしくは

$day01 = date("Y-m-d");

$day02 = date("Y-m-d",strtotime("-1 day"));

と言う風に15個の変数とSQL文が必要になると思うのです。

そうすると、処理が遅くなると思います。


私もLEFT JOINのようにNULLでも表示される方法を考えたのですが、なかなか難しそうですね。素直にPHPだけで完結したらいいのかな・・。

関連質問


●質問をもっと探す●



0.人力検索はてなトップ
8.このページを友達に紹介
9.このページの先頭へ
対応機種一覧
お問い合わせ
ヘルプ/お知らせ
ログイン
無料ユーザー登録
はてなトップ