93

次の MySQL テーブルを使用します。

+-----------------------------+
+ id INT UNSIGNED             +
+ name VARCHAR(100)           +
+-----------------------------+

でソートしたときに、テーブル内の他の行の中から単一の行とその位置を選択するにはどうすればよいですかname ASC。テーブル データが次のようになっている場合、名前で並べ替えると、次のようになります。

+-----------------------------+
+ id | name                   +
+-----------------------------+
+  5 | Alpha                  +
+  7 | Beta                   +
+  3 | Delta                  +
+ .....                       +
+  1 | Zed                    +
+-----------------------------+

Betaその行の現在の位置を取得する行を選択するにはどうすればよいですか? 私が探している結果セットは次のようになります。

+-----------------------------+
+ id | position | name        +
+-----------------------------+
+  7 |        2 | Beta        +
+-----------------------------+

PHP で簡単SELECT * FROM tbl ORDER BY name ASCに行を列挙することはできますが、1 行だけのために潜在的に大きな結果セットをロードするのは無駄に思えます。

4

9 に答える 9

130

これを使って:

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 になります。

于 2010-09-01T02:57:52.103 に答える
20

これが私が考えることができる唯一の方法です:

SELECT `id`,
       (SELECT COUNT(*) FROM `table` WHERE `name` <= 'Beta') AS `position`,
       `name`
FROM `table`
WHERE `name` = 'Beta'
于 2010-09-01T02:37:14.953 に答える
8

クエリが単純で、返される結果セットのサイズが大きくなる可能性がある場合は、それを 2 つのクエリに分割してみてください。

その行のデータを取得するためだけに絞り込みフィルター条件を使用する最初のクエリと、位置を計算するためにCOUNTwith句を使用する 2 番目のクエリ。WHERE

たとえば、あなたの場合

クエリ 1:

SELECT * FROM tbl WHERE name = 'Beta'

クエリ 2:

SELECT COUNT(1) FROM tbl WHERE name >= 'Beta'

2M レコードのテーブルでこのアプローチを使用します。これは、OMG Ponies のアプローチよりもはるかにスケーラブルです。

于 2012-03-12T07:34:50.657 に答える
3

テーブル内の行の位置は、対象の行よりも "優れている" 行の数を表します。

したがって、それらの行をカウントする必要があります。

SELECT COUNT(*)+1 FROM tableWHERE name<'ベータ'

同点の場合は最高位を返します。

既存の "Beta" 行の後に "Beta" という同じ名前の別の行を追加すると、返される位置は 2 のままです。これは、これらの行が分類内で同じ場所を共有するためです。

質問の所有者がすでに彼の問題を解決していると私は信じているので、これが将来同様のものを検索する人々に役立つことを願っています.

于 2014-05-23T16:53:13.253 に答える
3

非常によく似た問題があるため、同じ質問はしませんが、ここで何をしたかを共有します。group by と order by AVG も使用する必要がありました。署名とソコアを持つ学生がいて、それらをランク付けする必要がありました (つまり、最初に AVG を計算し、次に DESC で並べ替え、最後に位置 (ランク) を追加する必要がありました)。ここでの最良の答えと非常によく似ていますが、私の問題に合わせて少し変更されています):

最後にposition(私にとってのランク)列を外部SELECTに入れました

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 
于 2017-05-04T17:42:48.870 に答える
-13

あなたが必要とするのは add 構文です

LIMIT

だから使う

SELECT * FROM tbl ORDER BY name ASC LIMIT 1

1行だけ必要な場合..

于 2010-09-01T02:41:45.897 に答える