18

これは私のウェブサイトでの検索結果の注文に関する問題です。

検索を行うと、コンテンツページにランダムな結果が表示されます。このページにはページネーションも含まれています。私はSQLクエリとしてユーザーをフォローしています。

SELECT * FROM table ORDER BY RAND() LIMIT 0,10;

だから私の質問は

  1. ユーザーが次のページにアクセスするたびに、既に表示されている結果が再び表示されないようにする必要があります(次のクエリで、メモリ効率の高い方法で除外しますが、rand()で並べ替えます)

  2. 訪問者が最初のページに移動するたびに、異なる結果のセットがあります。これでページ付けを使用することは可能ですか、それとも順序は常にランダムになりますか。

  3. MYSQLでシードを使用できますが、実際にどのように使用するかわかりません。

4

6 に答える 6

55

RAND(SEED)を使用します。ドキュメントの引用:「定数整数引数Nが指定されている場合、シード値として使用されます。」(http://dev.mysql.com/doc/refman/5.0/en/mathematical-functions.html#function_rand)。

上記の例では、結果の順序はrandですが、常に同じです。シードを変更するだけで、新しい注文を取得できます。

SELECT * FROM your_table ORDER BY RAND(351);

ユーザーが最初の結果ページにアクセスするたびにシードを変更して、ユーザーセッションに保存できます。

于 2014-05-17T02:01:34.037 に答える
16

MySQLでのランダムな順序付けは、問題が発生するのと同じくらい厄介です。以前は、私は通常、可能な限り問題を回避することを選択しました。通常、ユーザーはこのような一連のページに1回または2回以上戻ることはありません。したがって、これにより、ランダムな順序のさまざまな嫌な実装のすべてを回避して、いくつかの単純な、しかし完全に100%ランダムではないソリューションを優先する機会が得られます。

解決策1

並べ替えのためにすでにインデックスが作成されている既存の列の数から選択します。これには、作成日、変更されたタイムスタンプ、またはその他の並べ替え可能な列を含めることができます。ASCユーザーが最初にサイトにアクセスしたときに、これらを配列で手元に用意し、ランダムに1つ選択してから、またはをランダムに選択しDESCます。

あなたの場合、ユーザーが1ページに戻るたびに、新しいものを選び、セッションに保存します。後続のすべてのページで、その並べ替えを使用して、一貫したページングのセットを生成できます。

解決策2

ソート用の乱数を格納する追加の列を作成できます。明らかに、インデックスを付ける必要があります。定期的に、次のクエリを実行します。

UPDATEテーブルSETrand_col= RAND();

これは、すべてのユーザーがページ1にアクセスするたびに異なるものを表示する必要があるように見えるため、仕様では機能しない場合があります。

于 2012-05-24T02:55:10.170 に答える
1

まず、ORDERBYRAND構文の使用を停止する必要があります。これは、大量の行セットのパフォーマンスに悪影響を及ぼします。

LIMIT制約を手動で決定する必要があります。それでもランダムな結果を使用したいが、ユーザーに次のページで同じ結果を表示させたくない場合は、この検索セッションのすべての結果をデータベースに保存し、ユーザーが次のページに移動するときにこの情報を操作するしかありません。

Webデザインで次に理解する必要があるのは、サイトでランダムなデータブロックを使用することは、ユーザーの視覚に非常に悪いことです。

于 2012-05-24T00:30:31.493 に答える
0

PHPにランダムなレコード番号または行を生成させて取得し、それらをクエリに渡し、ユーザーのクライアントにCookieを保存して、ユーザーが既に表示したレコードを示します。

そのユーザー固有のデータがサーバー上に存在する理由はありません(追跡している場合を除きますが、とにかくランダムなので、誰が気にしますか)。

于 2012-05-24T00:30:43.543 に答える
0

あなたは対処すべきいくつかの問題を抱えています!ステップバイステップで進むことをお勧めします。

最初の問題: 彼らがすでに見た結果は二度と現れない

  1. 返されたすべてのアイテムは、1つの配列に格納されます。(例のインデックスidを想定)
  2. ユーザーが次のページに移動したら、クエリにNOT IN:を渡します。

MySQLクエリ

SELECT * FROM table WHERE id NOT IN (1, 14, 25, 645) ORDER BY RAND() LIMIT 0,10;

idこれが行うことは、1、14、25、または645以外のすべてに一致することです。


パフォーマンスの問題に関する限り 、メモリ効率の高い方法で

SELECT RAND( )
FROM table
WHERE id NOT
IN ( 1, 14, 25, 645 )
LIMIT 0 , 10

行0〜9を表示(合計10、クエリに0.0004秒かかりました)

SELECT *
FROM table
WHERE id NOT
IN ( 1, 14, 25, 645 )
ORDER BY RAND( )
LIMIT 0 , 10

行0〜9を表示(合計10、クエリに0.0609秒かかりました)

したがって、ORDER BY RAND()は使用せず、できればSELECT RAND()を使用してください。

于 2012-05-24T00:37:11.113 に答える
0

の組み合わせ

  1. ランダムな順序
  2. ページ付け
  3. HTTP(ステートレス)

1.と2.は一緒に何らかの「永続的なランダム性」を必要としますが、3。はこれを達成するのを難しくします。これに加えて、1。はRDBMSが実行するように最適化された仕事ではありません。

私の提案は、データセットの大きさによって異なります。

数行(約<1K):

  • 最初のクエリですべてのPK値を選択します(最初のページ)
  • PHPでこれらをシャッフルします
  • シャッフルされたリストをセッションに保存する
  • ページ呼び出しごとに、保存されているPKに従ってデータを選択します

多くの行(10K +):

これは、管理可能な数の穴でAUTO_INCREMENT呼び出される一意のキーがあることを前提としています。ID必要に応じてamintenaceスクリプトを使用します(高い削除率)

  • たとえばセッションIDでパラメーター化されたシャッフリング関数を使用して、関数を作成しますrand_id(continuous_id)
  • たとえば、レコード100,000〜100,009が必要な場合は、$a=array(rand_id(100,000), rand_id(100,001), ... rand_id(100,009));
  • $a=implode(',',$a);
  • $sql="SELECT foo FROM bar WHERE ID IN($a) ORDER BY FIELD(ID,$a)";
  • IDの穴を処理するには、選択したレコードが少なすぎる(そしてexeを破棄する)数が多すぎるレコードを選択します。
于 2012-05-24T01:01:53.870 に答える