MySQL-選択時に行番号を取得する


181

アイテムがソートされている場合、selectステートメントを実行して行番号を取得できますか?

私はこのようなテーブルを持っています:

mysql> describe orders;
+-------------+---------------------+------+-----+---------+----------------+
| Field       | Type                | Null | Key | Default | Extra          |
+-------------+---------------------+------+-----+---------+----------------+
| orderID     | bigint(20) unsigned | NO   | PRI | NULL    | auto_increment |
| itemID      | bigint(20) unsigned | NO   |     | NULL    |                |
+-------------+---------------------+------+-----+---------+----------------+

次に、このクエリを実行して、ID別の注文数を取得できます。

SELECT itemID, COUNT(*) as ordercount
FROM orders
GROUP BY itemID ORDER BY ordercount DESC;

これによりitemID、次のように表のそれぞれの数がわかります。

+--------+------------+
| itemID | ordercount |
+--------+------------+
|    388 |          3 |
|    234 |          2 |
|   3432 |          1 |
|    693 |          1 |
|   3459 |          1 |
+--------+------------+

行番号も取得したいので、それitemID=388が最初の行であるか、2342番目であるかなどがわかります(基本的に、生のカウントだけでなく、注文のランキングです)。結果セットが返されたときにJavaでこれを実行できることはわかっていますが、純粋にSQLで処理する方法があるかどうか疑問に思っていました。

更新

ランクを設定すると、結果セットにランクが追加されますが、正しく順序付けされていません。

mysql> SET @rank=0;
Query OK, 0 rows affected (0.00 sec)

mysql> SELECT @rank:=@rank+1 AS rank, itemID, COUNT(*) as ordercount
    -> FROM orders
    -> GROUP BY itemID ORDER BY rank DESC;
+------+--------+------------+
| rank | itemID | ordercount |
+------+--------+------------+
|    5 |   3459 |          1 |
|    4 |    234 |          2 |
|    3 |    693 |          1 |
|    2 |   3432 |          1 |
|    1 |    388 |          3 |
+------+--------+------------+
5 rows in set (0.00 sec)

1
将来の参照用:ランク1からランク5にORDER BY rank ASC注文する場合は、(ASCの降順でのランクによる順序付け)を使用します。それはあなたの言っていることだと思いますが、適切に注文
BlueCacti

回答:


180

これを見てください。

クエリを次のように変更します。

SET @rank=0;
SELECT @rank:=@rank+1 AS rank, itemID, COUNT(*) as ordercount
  FROM orders
  GROUP BY itemID
  ORDER BY ordercount DESC;
SELECT @rank;

最後の選択はあなたのカウントです。


1
これは結果セットにランクを追加しますが、それらを適切な順序に配置しません-結果を含む更新された質問
George

1
を保持してORDER BY ordercount DESCSELECT最初のクエリからすべてを取得する別のクエリ全体をラップしますが、ランク列(この場合は0)で並べ替えます。
Mike Cialowicz

1
この例を示すことができますか?選択をラップするにはどうすればよいですか?
ジョージ

9
swamibebopの回答をチェック
thaddeusmt

1
@MikeCialowicz、これは動作しません。正しい答えについては、私のソリューションまたはSwamibebopのソリューションを参照してください。
Pacerier 2015

178
SELECT @rn:=@rn+1 AS rank, itemID, ordercount
FROM (
  SELECT itemID, COUNT(*) AS ordercount
  FROM orders
  GROUP BY itemID
  ORDER BY ordercount DESC
) t1, (SELECT @rn:=0) t2;

1
明確にしてくれてありがとう、これは私が抱えていた順不同の問題を解決しました。
thaddeusmt 2011年

1
ありがとう、これは私にとって本当に便利でした:)結果セットから行の「インデックス」を取得する簡単な方法がないことに驚いています...しかし、とにかくこれは便利でした。
ラット

SELECT \ @rn:= \ @ rn + 1 ASランク、itemID、ordercount、\ @ tot:= \ @ tot + ordercountをtotalcountとして変更することで、4番目の行を追加して、totalcountを増分できます。\ @totの初期値を定義するには、これをt2の後に追加する必要があります:(SELECT \ @tot:= 0)t3。すべての\ @の前の\を削除します。これは、ミニマークダウンフォーマットを回避するために使用する必要がありました。
Jan Ehrhardt 2014

2
誰かがt1and の関連性を説明できますt2か?
Jared、

2
@ Jared、MySQL構文では、そこに何かが必要です。それも、何もすることができますxy
Pacerier、2015

31

Swamibebopのソリューションは機能しtable.*ますが、構文を利用することで、内部の列名を繰り返すことを避けselect、より単純で短い結果を得ることができます。

SELECT @r := @r+1 , 
       z.* 
FROM(/* your original select statement goes in here */)z, 
(SELECT @r:=0)y;

だからそれはあなたに与えるでしょう:

SELECT @r := @r+1 , 
       z.* 
FROM(
     SELECT itemID, 
     count(*) AS ordercount
     FROM orders
     GROUP BY itemID
     ORDER BY ordercount DESC
    )z,
    (SELECT @r:=0)y;

@r := @r + 1selectステートメントでの使用が機能する理由を偶然知っていますが、それがを含むストアドプロシージャ内にある場合declare r int; set r = 0;、(onでr := r +1)文句を言いますか?
ダン・M.

@ Pacerier、2番目の選択の行の順序はどこかで保証されますか?order by句のないselectによって返される行の順序はどこでも保証されないことを知っています。最も外側のselectは正確ですが、内側の順序付けされたselectから選択するため、例外になる場合があります。ただし、そうでない場合は、Chibu's Mikeと同じ欠陥があるため、これが正しい解決策であるかどうかはわかりません。レコードの順序を選択してレコードに番号を付ける保証はありません。
Dan M.

フィールドリストにない場合にORDER BYが機能しない理由を教えてください。結果を見る:hastebin.com/aluqefunoy.rb

11

MySQL変数を使用してそれを行うことができます。このようなものが機能するはずです(ただし、2つのクエリで構成されています)。

SELECT 0 INTO @x;

SELECT itemID, 
       COUNT(*) AS ordercount, 
       (@x:=@x+1) AS rownumber 
FROM orders 
GROUP BY itemID 
ORDER BY ordercount DESC; 

2
注意してください。変数が評価されたorder by発生するため、これは機能しません。他の列を使用して注文して実験してみてください。また、両方を試してみると。それらが失敗することが多く、それが機能するのは唯一の場合であることがわかります。これは、元の「select」の順序がの順序と同じであるため、純粋な運によるものです。私のソリューションまたはSwamibebopのソリューションを参照してください。@xdescascorder by
Pacerier、2015

@Pacerierはあなたはそれについて確信していますか?別の例(基本的に数値の列から選択し、それらの順序に従って番号を付ける)で同様のクエリに疲れてきましたが、var / row numで順序付けすると、結果の行の順序が変更されたようです。しかし、各番号には同じ行番号がありました。しかし、数値列で並べ替えると、ASC/ DESCはそれらの番号が付けられた順序を変更します(最小から最大、またはその逆)。したがって、その場合order byは最初に評価されたように見えます。
Dan M.

1

これは現在、MySQL 8.0とMariaDB 10.2に組み込まれています。

SELECT
  itemID, COUNT(*) as ordercount,
  ROW_NUMBER OVER (PARTITION BY itemID ORDER BY rank DESC) as rank
FROM orders
GROUP BY itemID ORDER BY rank DESC
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.