次のMySQLテーブルを使用します。
+-----------------------------+
+ id INT UNSIGNED +
+ name VARCHAR(100) +
+-----------------------------+
name ASC
でソートされたときに、single行と、テーブル内の他の行の中のその位置を選択するにはどうすればよいですか。したがって、名前で並べ替えたときにテーブルデータが次のようになっている場合:
+-----------------------------+
+ id | name +
+-----------------------------+
+ 5 | Alpha +
+ 7 | Beta +
+ 3 | Delta +
+ ..... +
+ 1 | Zed +
+-----------------------------+
Beta
行を選択して、その行の現在の位置を取得するにはどうすればよいですか?私が探している結果セットは次のようなものです:
+-----------------------------+
+ id | position | name +
+-----------------------------+
+ 7 | 2 | Beta +
+-----------------------------+
簡単なSELECT * FROM tbl ORDER BY name ASC
を実行してからPHPで行を列挙できますが、1行だけの潜在的に大きな結果セットをロードするのはもったいないようです。
これを使って:
SELECT x.id,
x.position,
x.name
FROM (SELECT t.id,
t.name,
@rownum := @rownum + 1 AS position
FROM TABLE t
JOIN (SELECT @rownum := 0) r
ORDER BY t.name) x
WHERE x.name = 'Beta'
...一意の位置値を取得します。この:
SELECT t.id,
(SELECT COUNT(*)
FROM TABLE x
WHERE x.name <= t.name) AS position,
t.name
FROM TABLE t
WHERE t.name = 'Beta'
...タイに同じ値を与えます。 IE:2番目に2つの値がある場合、最初のクエリがそれらの一方に2の位置を与え、もう一方に3の位置を与えるとき、両方の位置は2になります...
これは私が考えることができる唯一の方法です:
SELECT `id`,
(SELECT COUNT(*) FROM `table` WHERE `name` <= 'Beta') AS `position`,
`name`
FROM `table`
WHERE `name` = 'Beta'
クエリが単純で、返される結果セットのサイズが潜在的に大きい場合は、クエリを2つのクエリに分割してみてください。
その行のデータを取得するためだけの絞り込みフィルター条件を使用した最初のクエリと、2番目のクエリはCOUNT
句とWHERE
句を使用して位置を計算します。
例えばあなたの場合
クエリ1:
_SELECT * FROM tbl WHERE name = 'Beta'
_
クエリ2:
SELECT COUNT(1) FROM tbl WHERE name >= 'Beta'
2Mレコードを持つテーブルでこのアプローチを使用します。これは、OMG Poniesのアプローチよりもはるかにスケーラブルです。
私は非常によく似た問題を抱えているので、同じ質問はしませんが、ここで私が何をしたかを共有します。AVGによるグループ化と順序付けも使用する必要がありました。署名とソコアを持つ学生がいて、それらをランク付けする必要がありました(つまり、最初にAVGを計算し、次にDESCでそれらを注文し、最後に位置を追加する必要がありました(ランク付け)ので、何か非常に似ているベストアンサーとして、ここで、私の問題に合わせて少し変更します):
最後に、外部SELECTにposition
(私のランク)列を追加しました
SET @rank=0;
SELECT @rank := @rank + 1 AS ranking, t.avg, t.name
FROM(SELECT avg(students_signatures.score) as avg, students.name as name
FROM alumnos_materia
JOIN (SELECT @rownum := 0) r
left JOIN students ON students.id=students_signatures.id_student
GROUP BY students.name order by avg DESC) t
テーブル内の行の位置は、ターゲット行よりも「良い」行の数を表します。
したがって、それらの行をカウントする必要があります。
SELECT COUNT(*)+ 1 FROM table
WHERE name
<'Beta'
同点の場合、最高位が返されます。
既存の「ベータ」行の後に「ベータ」という同じ名前の別の行を追加する場合、分類内で同じ場所を共有するため、返される位置は2のままです。
質問の所有者がすでに問題を解決したと思うので、これが将来似たようなものを検索する人々を助けることを願っています。
他の答えは私には複雑すぎるようです。
ここに簡単な例があります、列のあるテーブルがあるとしましょう:
userid | points
ユーザーIDをポイントでソートし、行の位置(ユーザーの「ランキング」)を取得するには、次を使用します。
SET @row_number = 0;
SELECT
(@row_number:=@row_number + 1) AS num, userid, points
FROM
ourtable
ORDER BY points DESC
num
は、行の位置(ランキング)を提供します。
MySQL 8.0以降を使用している場合は、 ROW_NUMBER() を使用できます。
私は受け入れられた答えを通り抜けていましたが、少し複雑に思えたので、ここに簡単なバージョンがあります。
SELECT t,COUNT(*) AS position FROM t
WHERE name <= 'search string' ORDER BY name