良く紹介されているのは、ユーザー変数を利用して、
set @i:=0;
select @i:=@i+1 as rownum,user_id from user;
という感じで、2つSQLを発行するパターン。
これを1つのSQLで行う方法があった。
select @i:=@i+1 as rownum,user_id from (select @i:=0) as dummy,user;
サブクエリでユーザー変数を初期化している。
こんな発想はなかったなぁ。素晴らしい。
これでそれっぽく行番号を取得できるのだが、
MySQLのサイトの8.4. ユーザによって定義された変数にて、以下の内容があった。
ユーザ変数の評価順序は定義されておらず、与えられたクエリ内の要素に基づいて変更されることがあります。SELECT @a, @a := @a+1 ...では、MySQLは@aを先に評価し次に割り当てが実行されるように見えますが、クエリの変更(例えばGROUP BY、HAVINGまたはORDER BY節による変更)は評価順序を変更する可能性があります。
よって、order byした場合は意図しない結果になるかもしれないので要注意。
あと、似たような機能で、順位を取得する場合のSQLも見つけたので、記録。これは単純な行番号ではなくて、順位形式なので、同順位の場合もある。ただ、自己結合で直積してて、データ数が多い場合は、非常に遅いのが難点だ。
SELECT
s0.sale_code,
s0.sale_cgcode,
s0.sale_cgsubcode,
s0.sale_cnt,
count(s1.sale_code) + 1 as sale_rank
FROM
sale_tbl s0 LEFT OUTER JOIN sale_tbl s1 ON
s0.sale_cnt < s1.sale_cnt
GROUP BY
s0.sale_code,
s0.sale_cgcode,
s0.sale_cnt
ORDER BY
sale_cnt desc