FIND_IN_SET()を使ってカンマ区切りのキーでテーブルをJOINする

 例えばここに、書籍のテーブルbooksと、カテゴリのテーブルマスタcategoriesがあったとする。
で、booksはcategory_idを外部キーにして、書籍のカテゴリを持つわけである。
問題は、booksのレコードが複数のカテゴリに多重に属せるような要件の場合だ。
category_id_1〜category_id_xのように、x個のカラムを作るようなことをしていると、何重に属せるかが固定の上限値を持つようになり、汎用性がなくなってしまう(運用上カテゴリがどんどん増えていく事を想定する場合)。
とはいえ、RDBでは動的に外部キーを増減させる必要があったとしても対応できなさそうに思える。


 そんな場合、category_idのカラムをテキスト型にして、「,」区切りで外部キーを持つような形にするわけだ。「,」で区切りながら一つのカラムに無制限に外部キーを足していける。
PHPであれば、implodeやexplodeで、このカラムの区切り文字をうまく扱える。
だが、この「,」区切りの外部キーで、どうやってテーブルを結合させればいいのだろうか?


 MySQLでは、FIND_IN_SET()を使えばいい。

SELECT * FROM books INNER JOIN categories ON FIND_IN_SET(categories.id, books.category_id) >= 1

 FIND_IN_SET()は「,」で区切られた文字列のリストに、与えられた文字列が含まれているなら何番目に含まれているか返すだけだが、
結合の条件に使用すれば、「,」区切りの外部キーにcategoriesのidが含まれているものを結合してくれる。


参考:
 MySQL 5.6 リファレンスマニュアル / 関数と演算子 / 文字列関数 / 12.5 文字列関数
 https://dev.mysql.com/doc/refman/5.6/ja/string-functions.html#function_find-in-set
 外部キーがカンマ区切りテキストなテーブルにJOINする
 http://qiita.com/rryu/items/86f0dd8a3d63db27e5c9