Kouhei Sutou
kou****@clear*****
2014年 6月 26日 (木) 11:06:48 JST
須藤です。 In <20140****@clear*****> "[groonga-dev,02444] Re: 「GROUP BY」条件をmroonga_command()で再現する方法" on Tue, 24 Jun 2014 15:02:17 +0900 (JST), Kouhei Sutou <kou****@clear*****> wrote: >> Mroongaストレージエンジンからのmroonga_command()による全文検索を勉強中です。 >> 今は、過去に「GROUP BY」を使って実装していた処理を、Groongaコマンドに移し替えようとして四苦八苦しています。 >> 具体的には、たとえば以下のような処理を行いたいのですが、Groongaの--drilldownなり、他のオプションなりで実現できるでしょうか? > > SET NAMES utf8; > > CREATE TABLE t ( > id int primary key auto_increment, > name varchar(255), > kana varchar(255) > ) ENGINE = Mroonga DEFAULT CHARSET = utf8; > > INSERT INTO t (name, kana) VALUES ("トム", "とむ"); > INSERT INTO t (name, kana) VALUES ("ジェリー", "じぇりー"); > INSERT INTO t (name, kana) VALUES ("十夢", "とむ"); > INSERT INTO t (name, kana) VALUES ("ミッキー", "みっきー"); > INSERT INTO t (name, kana) VALUES ("トム", "とむ"); > > というスキーマとデータで > > SELECT *, count(id) AS c FROM t GROUP BY name ORDER BY kana ASC LIMIT 10; > > 相当のことをmroonga_commandで実現できるか?ということですね! > > ちょっと試してみたのですが、できませんでした。。。 > > 本当は > > SELECT mroonga_command("select t --limit 0 --drilldown_limit 10 --drilldown_offset 0 --drilldown_output_columns _key,id,kana,_nsubrecs --drilldown name --drilldown_sortby kana") AS result; > > ポイントは--drilldown_sortbyで、整形するとこんな感じ: > > select t > --limit 0 > --drilldown_limit 10 > --drilldown_offset 0 > --drilldown_output_columns _key,id,kana,_nsubrecs > --drilldown name > --drilldown_sortby kana > > で動いて欲しいところなんですが、今の実装だ > と--drilldown_sortbyに実カラムの指定をサポートしていませんで > した。(_nsubrecsなど擬似カラムは指定できる。) すみません。これ、ウソでした。動いて欲しいところではなかった です。これだと、グループ化したうち、どのレコードのkanaの値を 使うの?問題が発生するのでスジがよくなかったです。 > INSERT INTO t (name, kana) VALUES ("トム", "とむ"); > INSERT INTO t (name, kana) VALUES ("トム", "とむ"); というように2回「トム」→「とむ」を入れていますが、 INSERT INTO t (name, kana) VALUES ("トム", "とむ"); INSERT INTO t (name, kana) VALUES ("トム", "トム"); とか、kanaの値が違うと問題になります。なので、この場合は、 CREATE TABLE names ( name varchar(255) PRIMARY KEY, kana varchar(255) ) ENGINE = Mroonga DEFAULT CHARSET = utf8; CREATE TABLE t ( id int primary key auto_increment, name varchar(255) COMMENT 'type "names"' ) ENGINE = Mroonga DEFAULT CHARSET = utf8; というように正規化してください。で、こんな風にデータをいれて、 INSERT INTO names (name, kana) VALUES ("トム", "とむ"); INSERT INTO names (name, kana) VALUES ("ジェリー", "じぇりー"); INSERT INTO names (name, kana) VALUES ("十夢", "とむ"); INSERT INTO names (name, kana) VALUES ("ミッキー", "みっきー"); INSERT INTO t (name) VALUES ("トム"); INSERT INTO t (name) VALUES ("ジェリー"); INSERT INTO t (name) VALUES ("十夢"); INSERT INTO t (name) VALUES ("ミッキー"); INSERT INTO t (name) VALUES ("トム"); JOINしてください。 SELECT *, count(id) AS c FROM t INNER JOIN names ON t.name = names.name GROUP BY t.name ORDER BY names.kana ASC LIMIT 10; これならnameのkanaは必ず一意に決まるのでどのレコードを使うの 問題は発生しません。 そして、このスキーマならGroongaでも動きます。 SELECT mroonga_command("select t --limit 0 --drilldown name --drilldown_limit 10 --drilldown_output_columns _key,id,kana,_nsubrecs --drilldown_sortby kana") AS result; 整形するとこうです。 select t --limit 0 --drilldown name --drilldown_limit 10 --drilldown_output_columns _key,id,kana,_nsubrecs --drilldown_sortby kana ということで、テーブルを正規化してください!が回答になります! -- 須藤 功平 <kou****@clear*****> 株式会社クリアコード <http://www.clear-code.com/> Groongaサポート: http://groonga.org/ja/support/ パッチ採用: http://www.clear-code.com/recruitment/ コードリーダー育成支援: http://www.clear-code.com/services/code-reader/