0

フィールドID、投票(ユーザーごと)、評価を含むテーブルがあります。

タスク: 自分と他のユーザーへの投票に基づいて、ユーザーの評価を数えます。つまり、フィールド投票を更新するたびに、フィールド評価の再計算が必要でした。

つまり、一部は 3 位になる可能性があります。彼に投票した場合、彼は 2 位まで、もう一方の場合はその逆 - 2 から 3 まで (評価フィールドで)

この問題を解決するには?フィールドを更新して php でユーザーの評価をカウントし、mysql で多くの更新クエリを実行するたびに、非常にコストがかかります。

4

5 に答える 5

1

まあそれは多くの要因に依存します

  1. 指数関数的に成長している大規模なシステムがありますか?
  2. 履歴レポートに投票データが必要ですか?
  3. ユーザーは投票時に登録する必要がありますか?
  4. このシステムは、システムのライフサイクル全体で1つの投票タイプにのみ使用されますか、それともさまざまな主題に対してより多くの投票が行われますか?

すべての答えがNOの場合、現在の更新方法は問題なく機能します。とにかく、ベストコーディングとMySQLテーブルプラクティスを適用していることを確認してください。

ほとんどまたはすべての答えが「はい」であると仮定して、次のことを提案します。

  • 投票が行われるたびにINSERT、レコードがテーブルに記録されます
  • を使用しINSERTて、タイムスタンプ、不可能な場合はユーザーIDを追加し、IPアドレス/場所を追加します。
  • 投票_subjectテーブルから外部キーとしてサブジェクトIDを割り当てます。この表には、投票の件名と日付を保存します
  • SELECTこれで、投票をカウントして評価を計算できるステートメントを作成できます。投票数リストのトップの人は、で評価1を取得しSELECTます。さらに、被験者ごと、日ごと、ユーザーごとにフィルタリングすることができ、必要な結果に応じてボリュームを決定することもできるはずです。

もちろん、これはすべて、システムが将来どのように拡張されるかに依存します。これはやり過ぎかもしれませんが、考えるべきことがあります。

于 2012-09-21T16:58:08.653 に答える
1

評価列を持たない選択で評価を取得したい場合は、これが方法です。ただし、パフォーマンスの観点から、これが最良の選択肢であるとは保証できません。仕組みとしては、2 人のユーザーが同じ投票数を持っている場合、同じ評価が与えられ、次の異なる評価に必要な数だけスキップされます。

set @rating:=0;
set @count:=1;

select id,
case when @votes<>votes then @rating:=@rating+@count
else @rating end as rating,
case when @votes=votes then @count:=@count+1
else @count:=1 end as count,
@votes:=votes as votes
from t1
order by votes desc

sqlfiddle

これにより、無視できる余分な列が得られます。または、この選択をサブクエリにラップして、次のようにすることもできます。

select t2.id,t2.votes,t2.rating from (
select id,
case when @votes<>votes then @rating:=@rating+@count
else @rating end as rating,
case when @votes=votes then @count:=@count+1
else @count:=1 end as count,
@votes:=votes as votes
from t1
order by votes desc) as t2

しかし、sqlfiddleは不思議なことに一貫性のない結果を出しているので、テストを行う必要があります。誰かがこれがなぜなのか知っているなら、私はその理由を知りたいと思います.

1 人のユーザーだけの評価を取得したい場合は、サブクエリ オプションを実行し、whereafterを使用するfromと、目的の結果が得られます。sqlfiddle - しかし、繰り返しますが、結果に一貫性がありません。数回実行すると、評価が 10 になることもあれば、30 になることもあります。データベースでテストして、何が起こるかを確認するのが最善だと思います。

于 2012-09-21T17:05:14.147 に答える
0

フィールド id、votes、rating の代わりに、フィールド id、rating_sum、rating_count を持つようにテーブルを変更します。新しい評価があるたびに、次のようにデータベースにクエリを実行します。

    "UPDATE `ratings` SET `rating_count` = `rating_count` + 1, `rating_sum` = `rating_sum`+ $user_rating WHERE `id` = $id"

現在、評価は単なる平均 -> rating_sum / rating_count です。評価のあるフィールドを持つ必要はありません。

また、ユーザーの評価が複数回発生するのを防ぐために、users.id と rating.id という 2 つの外部キーを持つ rating_users という名前のテーブルを作成できます。主キーは (users.id、ratings.id) になります。したがって、ユーザーが最初に評価しようとするたびに、この表を確認します。

于 2012-09-21T16:45:52.920 に答える
0

はい、集約は高価です。5 分ごとにランク テーブルを更新し、そこからクエリを実行できます。クエリはおそらく既に次のとおりです。

select id, count(*) as votes
from users
group by id
order by votes desc
于 2012-09-21T16:46:31.203 に答える
0

データをクエリするときにこれを行うことをお勧めします。それははるかに簡単です。投票数の多い順に並べます。

おそらく、ビューを作成し、データのクエリを実行するときにそのビューを使用します。

次のようなことを試すことができます:

SET @rank := 0

select id, count(*) as votes, @rank := @rank + 1
from users
group by id
order by votes desc

または

SET @rank := 0

select id, votes, @rank := @rank + 1
from users
order by votes desc
于 2012-09-21T16:37:22.337 に答える