裏MySQLクエリー入門(14) 番外編1 複数カテゴリーの正しいデータの持ち方
裏MySQLクエリー入門(13)で出したサンプルですがデータ構造としては最悪です。これは実際に遭遇したデータ構造なのですが、これは、プログラマーがメインの人が良くやってしまうデータ構造ですね。カテゴリーIDを文字列として、カンマ区切りで格納...。気持ちは分からなくないですが、FIND_IN_SETを使ったトリッキーな結合*1を行う必要があったり、かえって大変な事になります。
また、varchar(255)*2がカテゴリーの格納領域となる為、以下のように最大88カテゴリーしか保存できません。
1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88
それでは、これを正しく修正してみましょう。
- まずカテゴリ用テーブルを新規に作成します。
CREATE TABLE IF NOT EXISTS `platform_program` ( `platform_id` int(11) NOT NULL COMMENT 'プラットフォームID', `program_id` int(11) NOT NULL COMMENT 'プログラムID', PRIMARY KEY (`platform_id`,`program_id`), KEY `platform_id` (`platform_id`), KEY `program_id` (`program_id`) ) ENGINE=MyISAM DEFAULT CHARSET=cp932 COMMENT='プラットフォームプログラム';
- カテゴリー用のデータを作ります。
SELECT platform_id,program_id FROM `platform` pf, `program` pg WHERE FIND_IN_SET( pg.program_id, pf.program_ids ) >0
platform_id | program_id |
---|---|
1 | 1 |
1 | 2 |
1 | 3 |
2 | 1 |
2 | 2 |
2 | 3 |
3 | 1 |
3 | 2 |
3 | 3 |
3 | 4 |
4 | 4 |
5 | 1 |
5 | 2 |
- 作ったデータをカテゴリーテーブルに流し込みます。
INSERT INTO platform_program (platform_id,program_id) SELECT platform_id,program_id FROM `platform` pf, `program` pg WHERE FIND_IN_SET( pg.program_id, pf.program_ids ) >0
- プラットフォームテーブルからprogram_idsを削除
ALTER TABLE `platform` DROP `program_ids`
- 以上3つのテーブルを結合して上げれば完成です。
SELECT pf.platform_id,pf.platform_name,pg.program_id,pg.program_name FROM `platform` pf, platform_program pp, program pg WHERE pf.platform_id = pp.platform_id AND pp.program_id = pg.program_id ORDER BY pf.platform_id
platform_id | platform_name | program_id | program_name |
---|---|---|---|
1 | Windows | 1 | JAVA |
1 | Windows | 2 | ActionScript |
1 | Windows | 3 | PHP |
2 | Linux | 1 | JAVA |
2 | Linux | 2 | ActionScript |
2 | Linux | 3 | PHP |
3 | Mac OS X | 1 | JAVA |
3 | Mac OS X | 2 | ActionScript |
3 | Mac OS X | 3 | PHP |
3 | Mac OS X | 4 | Objective-C |
4 | iphone | 4 | Objective-C |
5 | Android | 1 | JAVA |
5 | Android | 2 | ActionScript |
- 3テーブル結合はちと面倒くさいので、この程度のレベルであればviewを作るのもアリかと
CREATE OR REPLACE ALGORITHM = UNDEFINED VIEW `v_platform` AS SELECT pf.platform_id, pf.platform_name, pg.program_id, pg.program_name FROM `platform` pf, platform_program pp, program pg WHERE pf.platform_id = pp.platform_id AND pp.program_id = pg.program_id ORDER BY pf.platform_id