3

現在、次の属性を持つデータを返すクエリがあります。

  • 結果で一意であることが保証されている数値A (ソーステーブルではない)。結果はA順に並べられますが、結果のAの値は必ずしも連続しているとは限りません。
  • 同じグループの一部としてタグ付けされた、複数の行に対して繰り返されるキーB。Aと同じテーブルから来ています。

例:

+--+-+-+
|id|A|B|
+--+-+-+
| 5|1|2|
|15|3|2|
|12|4|5|
|66|6|5|
| 2|7|2|
+--+-+-+

結果で行番号を返す方法を説明する回答をここで確認しました。ただし、私が必要としているのは、Bごとに個別のカウントを維持しながら、(できれば1ベースの)注文番号を取得することです。次の表では、Cが望ましい結果です。

+--+-+-+-+
|id|A|B|C|
+--+-+-+-+
| 5|1|2|1|
|15|3|2|2|
|12|4|5|1|
|66|6|5|2|
| 2|7|2|3|
+--+-+-+-+

これは私の現在のSQLスキルを少し超えているので、ポインタに感謝します。既存の回答へのポインタを含みます!

編集:以下の両方の回答は、結果に関して同じように機能します(並べ替えに使用されるダミーのラッピングクエリを使用)。助けてくれてありがとう。最も効率的なクエリはどれですか?私の特定のユースケースでは、元のクエリから返される行の量が非常に多くなることは決してないことを考慮してください(たとえば、最大50行、それでも想像力の範囲です)。また、元のクエリには、他のリレーションからデータをフェッチするために使用される結合がありますが、それらは並べ替えやフィルタリングには関係ありません。最後に、すべての結果が同じBを持つことも、すべての結果が異なるBを持つことも可能です。これは、どちらの方向にも、またはその間のどこにでも行くことができます。

4

3 に答える 3

6

基本的に欲しいのはRANK()関数です。ただし、MySQLでは使用できないため、次の方法でシミュレートできます。

SELECT *
FROM (
  SELECT a, b, (CASE b 
                WHEN @partition THEN @rank := @rank + 1 
                ELSE @rank := 1 AND @partition := b END) AS c
  FROM tbl, (SELECT @rank := 0, @partition := '') tmp
  ORDER BY b, a
) tmp
ORDER BY a

デモ(SQLフィドル)。

于 2012-08-24T12:16:10.503 に答える
4
select p.*, @i := if(@lastB != p.B, 1, @i + 1)
,@lastB := p.B as B
from table_name p, 
(select @i := 0) vt1,
(select @lastB := null) vt2
order by B;

このコードを試してください。(未検証)

sqlfiddle でデモを編集http://sqlfiddle.com/#!2/412df/13/2

于 2012-08-24T12:15:04.450 に答える
0

クエリを2回計算してから、group byも実行する必要があるため、これはあまり効率的ではありません。

SELECT 
    q.* ,
    COUNT(*) AS c              --- the "Rank"
FROM 
    yourQuery AS q
  JOIN
    yourQuery AS qq
      ON  qq.B = q.B
      AND qq.A <= q.A
GROUP BY
    q.A ;
于 2012-08-24T12:20:36.020 に答える