同一アビリティでレベルによって更新されるものがあるが、検索結果にはHitするもの全てを表示するようにしている。しかしデータが増えてくると、バリエーションが多い(といっても、最大で3だが)アビリティは少々うざくなる。行数制限なども必要になってくるので、同じアビリティに関しては1行で表示するオプションが必要なのは承知していた。(そのつもりでチェックボックスは既に用意してあった)
SQLで重複行をまとめるのであれば「DISTINCT」しかないだろう。
SELECT COUNT(DISTINCT detail.ab_id) FROM ab_detail_tbl detail
こうかけば、重複しているIDはまとめられて1行としてカウントされる。では、実際のデータのSELECTはどうするか?
SELECT DISTINCT detail.ab_id, detail.ab_name, detail.ab_type
FROM ab_detail_tbl detail
こんな感じに通常だとなるのだが、同じidなら当然名前も同じなのでいいのだけれど、タイプによってレコードを分けている関係上これは意図した通りにまとまらない。つまり、ab_typeが同一ab_idで複数存在した場合にまとめる事ができない。
PostgreSQLの場合にはこれは次のように書けるらしい。
SELECT DISTINCT ON(detail.ab_id), detail.ab_name, detail.ab_type
FROM ab_detail_tbl detail
しかしながら、残念な事のMySQLではこれは採用されていないようだ。ではどうするか。サブクエリを発行してそこから重複ID分を除くという手段もあるようだったが、GROUP BYが使えるような感じだった。次のような感じ。
SELECT detail.ab_id, detail.ab_name, detail.ab_type
FROM ab_detail_tbl detail GROUP BY detail.ab_id
試してみると、意図通りにCOUNTと同じくIDだけに着目した重複のまとめが実現できた。DISTINCTじゃなく、GROUP BYだと実際SELECTされてからキャッシュ内でまとめ処理が走るような気がするので、性能的な懸念はあるのだが、それはサブクエリとそんなに差は無いのではないだろうか?そして、そもそも大量データになる場合はカウントで除外するようになっているので、致命的な性能劣化はおきないのでは?と考えている(というか期待している)。
テストはこれで実施してみよう。

