JOINを使用して、データベースが1つのクエリとして最適化できるようにします。
SELECT u.uid, COUNT(l.id)
FROM Users u -- or whatever your users table is named
LEFT JOIN logs l
ON l.uid = u.uid AND l.time + l.date > $timeNow
GROUP BY u.uid
英語では、これはデータベースに「ユーザーIDとそれに関連付けられたログの数のリストを取得します。ここで、time + date
は後になります$timeNow
」と通知します。これは、データベースにすべての作業を一度に提供するため、非常に効率的です。したがって、一度に1つずつ取得するのではなく、すべての情報を取得するための最適な方法を見つけることができます。
参加する
はLEFT JOIN
、usersテーブルとlogsテーブルが同じであるレコードを検索することにより、ユーザーとログを照合するようにデータベースに指示しますuid
。LEFT
inは、ユーザー(結合の右側)にログが関連付けられていない場合でも、ユーザー(結合の左側)のLEFT JOIN
結果を返すようにデータベースに指示します。ユーザーのログがない場合の結果を表示したくない場合は、を実行できます。これにより、結合の両側(ユーザーと少なくとも1つのログメッセージの両方)に一致する結果のみが表示されます。INNER JOIN
グループ化
結果をユーザーIDでグループ化する必要があります。そうしないと、任意のGROUP BY
ユーザーに関連付けられたログメッセージの総数を取得するだけで、おそらくは役に立たない可能性があります。SELECT COUNT(*) FROM logs
私はテーブルエイリアスを使用してクエリを短くしています。これは私がいつも使用しているスタイルだからですが、テーブルのフルネーム(logs.uid
など)を簡単に入力できます。テーブル名を含めなくても回避できる場合もありますが、クエリで複数のテーブルに存在する列を参照するとデータベースが混乱するため、どの列を常に明示するのが最も簡単だと思います。話し直します。
インデックス
この新しいクエリは、データベースがめちゃくちゃ大きい場合を除いて、すぐに終了するはずです。そうでない場合は、@ charlyのアドバイスを受けて、いくつかのインデックスを試してください。残念ながら、l.time + l.date
値を使用する前に追加します。MySQLでインデックスを作成できるとは思いませんが、最初l.time + l.date
にフィルタリングすることで適切な結果を得ることができる場合がありますl.date
(これはインデックス可能です)。
ON l.uid = u.uid AND l.date > $timeNow AND l.time + l.date > $timeNow
これは繰り返しのように見えますが、次のことができるため、データベースでの作業が増えます。
- インデックスを使用した
l.date
後の結果を取得します。$timeNow
- その(できれば小さい)結果のセットを。でフィルタリングし
l.time + l.date > $timeNow
ます。
それ以外の:
- テーブル内のすべてのレコードに対して、を追加し
l.time + l.date
ます。
- その結果が後かどうかを確認します
$timeNow
PHP
PHPでこれを行うには、次のようなことを行います。
$sql = // that query above
$result = mysql_query($sql);
while($row = mysql_fetch_array($result)) {
echo "User " . $row[0] . " posted " . $row[1] . " times.";
}
または、これをより複雑な方法で使用する必要がある場合は、すべてを事前に取得してください。
$counts = array();
$sql = // that query above
$result = mysql_query($sql);
while($row = mysql_fetch_array($result)) {
$counts[$row[0]] = $row[1];
}
// later
$user = 5; // some user we care about
echo "User " . $user . " posted " . $counts[$user] . " times.";
「すべてを前もってフェッチする」方法で行う場合は、INNER JOIN
含まれていないユーザー$counts
のカウントが0であるという知識を持ったバージョンのクエリを使用して、少し最適化することもできます。
私の構文が間違っている場合は申し訳ありませんが、これはアイデアを示していると思います。
セキュリティノート
マイナーな接線で:変数をクエリに直接ドロップしているように見えますが、これは一般的に悪い考えです。非常に複雑なソリューションは数多くありますが、最も簡単なのは、パラメーター化されたクエリを使用し、変数をSQLに直接配置しないことです。