多くの行を持つ MySQL テーブルがあります。表には人気欄があります。人気順で並べ替えると、各アイテムのランクがわかります。テーブル全体をソートせずに、特定のアイテムのランクを取得することはできますか? 私はそうは思わない。あれは正しいですか?
別の方法は、ランクを格納するための新しい列を作成し、テーブル全体を並べ替えてから、すべての行をループしてランクを更新することです。それは非常に非効率的です。おそらく単一のクエリでこれを行う方法はありますか?
最初にテーブルをソートしたり、ランクを保存したりせずに、何かの順序 (いわゆるランク) を計算する方法はありません。
ただし、テーブルが適切にインデックス化されている場合 (人気のインデックス)、データベースがこれを並べ替えてランクを取得するのは簡単です。次のようなものをお勧めします。
SET @rank := 0;
SELECT t.*, @rank := @rank + 1
FROM table t
ORDER BY t.popularity;
特定の「id」を持つアイテムを取得するには、次のようにサブクエリを使用できます。
SET @rank := 0;
SELECT * FROM (
SELECT t.*, @rank := @rank + 1
FROM table t
ORDER BY t.popularity
) t2
WHERE t2.id = 1;
InnoDbテーブルを使用している場合は、人気の列にクラスター化インデックスを作成することを検討してください。(人気による注文が頻繁なクエリである場合のみ)。決定は、人気の列がどれほど多様であるかにも依存します(0〜3はあまり良くありません)。
クラスタ化されたインデックスに関するこの情報を見て、これが自分のケースで機能するかどうかを確認できます:http: //msdn.microsoft.com/en-us/library/ms190639.aspx
これはSQLサーバーを指しますが、概念は同じです。これに関するmysqlのドキュメントも参照してください。
テーブルが読み込まれるたびにランク列が更新される場合、2 番目のアプローチが非効率的であることは間違いありません。ただし、データベースへの更新の数に応じて、更新ごとにランクを計算し、それを保存できます。これは、キャッシュの形式です。次に、計算フィールドを固定値フィールドに変換します。
このビデオでは、mysql でのキャッシングについて説明します。これは Rails 固有のものであり、キャッシングの形式が少し異なりますが、非常によく似たキャッシング戦略です。
PDO を使用してこれを行っている場合は、適切に機能させるために、すべてが単一のステートメント内に収まるようにクエリを変更する必要があります。PHP/PDO/MySQL: 複数のクエリを単一のクエリに変換するを参照してください。
したがって、hobodave の答えは次のようになります。
SELECT t.*, (@count := @count + 1) as rank
FROM table t
CROSS JOIN (SELECT @count := 0) CONST
ORDER BY t.popularity;
hobodave のソリューションは非常に優れています。または、別のランク列を追加し、行の人気度がUPDATE
d の場合は常にクエリを実行して、その人気度の更新がその上下の行と比較してランキングを変更したかどうかを判断しUPDATE
、3 つの行が影響を受ける可能性があります。どちらの方法がより効率的かを確認するには、プロファイルを作成する必要があります。