0

SQLの質問があります。まず第一に、SQLだけでも可能かどうかを知りたいのですが、そうでない場合は、良い回避策を知っている人はいません。

ユーザーが動画に投票できるサイトを構築しています。
ユーザーは、SMS で投票するか、Facebook 認証後にサイトで直接投票できます。
すべての動画のトップ リストを作成し、各動画のリストの「位置」を計算する必要があります。

これまでのところ、次のような単純なサブクエリでそれを行ってきました。

SELECT v.video_id AS id, 
    (SELECT (COUNT(*)+1) FROM videos AS v2 
        WHERE (v2.SMS_votes + v2.facebook_votes) > (v.SMS_votes + v.facebook_votes)) AS total_position 
FROM videos AS v

SMS_votesおよびfacebook_votesは集約されたフィールドです。投票の種類ごとに個別のテーブルがあり、投票が設定された時間を含む各投票の記録があります。

これは正常に機能し、順位が計算されます... 2 つ以上の動画の投票数が同じ場合、それらは順位を「共有」します。

残念ながら、位置の共有はあり得ないため、次のルールに従って解決する必要があります。

  • 2 つの動画の投票数が同じ場合は、SMS 投票の多い方が有利です。
  • それらが同じ数の SMS 票を持っている場合、過去 1 時間でより多くの SMS 票を持っている方が有利です。
  • 過去 1 時間の SMS 投票数も同じ場合、前の 1 時間ごとに比較され、2 つに差が出るまで再帰的に比較されます。

この種の再帰的な順序付けを SQL でのみ行うことは可能ですか、それともコードで手動で解決する必要がありますか? すべてのアイデアを歓迎します。トップリストはサイト全体で使用されるため、ここではパフォーマンスが重要です。

4

1 に答える 1

0

この種の順序付けを再帰的計算 (潜在的に無制限) で実行するのは現実的ではないと思いますが、振り返る時間を制限したい場合は、それを行う方法があります。

ここに 1 つの可能性があります。

SELECT video_id,
  SMS_votes + facebook_votes AS total_votes,
  SMS_votes,
  COUNT(CASE WHEN time > NOW() - INTERVAL 1 HOUR THEN 1 END) AS h1,
  COUNT(CASE WHEN time > NOW() - INTERVAL 2 HOUR THEN 1 END) AS h2,
  COUNT(CASE WHEN time > NOW() - INTERVAL 3 HOUR THEN 1 END) AS h3
FROM videos
JOIN SMS_votes USING(video_id)
GROUP BY video_id
ORDER BY total_votes DESC, SMS_votes DESC, h1 DESC, h2 DESC, h3 DESC;

これは、各投票を追跡するSMS_votesというテーブルがあり、 video_idフィールドとtimeフィールドがあることを前提としています。

ビデオごとに、合計投票数、SMS 投票数、過去 1 時間、過去 2 時間、過去 3 時間の SMS 投票数を計算します。次に、ORDER BYこれらすべての値に対して を実行して、正しい位置を取得します。

これを拡張してより広い時間範囲を含めるのはかなり簡単ですが、時間をさかのぼるにつれて時間範囲を増やして使用することを検討することもできます。たとえば、最初に過去 1 時間の投票を確認し、次に過去 1 日、次に過去 1 週間の投票を確認します。これにより、多くの計算を追加しなくても、動画が同じ投票を獲得する可能性が低くなると思います。

SQL フィドルの例

于 2013-07-04T17:38:49.717 に答える