人力検索はてな
モバイル版を表示しています。PC版はこちら
i-mobile

MySQL

以下を実現するSQLをお願いします。

テーブル bookinfo

id auto_increment
select varchar(10)
booktitle text
bookid varchar(45)
bookcate varchar(20)

検索機能を作成しているのですが、本のカテゴリーが bookcate に "テクノロジー" や "English" のように入力されています。 ひとつの本でもカテゴリが複数ある場合があるので、その際には書くカテゴリごとにレコードを作製し入力し、bookidでまとめています。
たとえば絞込みで カテゴリが "絵本","学習","低学年向け" の本を検索したいのですが、

select * from bookinfo where select = "all" AND bookcate in ("絵本","学習","低学年向け") で検索すると、カテゴリに 絵本 が含まれるのもすべてがSELECTされてしまいます。

そうではなくて、bookidが同じもので3つのカテゴリが入っているものをはじめてSELECTするSQLをお願いします。





●質問者: esecua
●カテゴリ:コンピュータ ウェブ制作
✍キーワード:ALL English MySQL SELECT SQL
○ 状態 :終了
└ 回答数 : 5/5件

▽最新の回答へ

1 ● icchan0000
●10ポイント

select * from bookinfo

where bookid in (select bookid from bookinfo where bookcate ='絵本')

and bookid in (select bookid from bookinfo where bookcate ='学習')

and bookid in (select bookid from bookinfo where bookcate ='低学年向け')

ではどうでしょうか?

◎質問者からの返答

ありがとうございます。

確かにできるかもしれませんが、一回につき数個のSELECTをかけてしまっているので、負荷問題が心配です。

もっと効率のいい方法はないでしょうか?


2 ● kurukuru-neko
●15ポイント

カラム名に予約語selectは使用出来ない

事はありませんがそのままでは使用できません。

必ず`select`と書く必要があります。

select * from bookinfo as b1

where `select`="all"

and bookcate in ("絵本","学習","低学年向け")

and ("絵本","学習","低学年向け")

=( (select bookcate from bookinfo as b2 where b2.bookid=b1.bookid and b2.bookcate="絵本" limit 1),

(select bookcate from bookinfo as b2 where b2.bookid=b1.bookid and b2.bookcate="学習" limit 1),

(select bookcate from bookinfo as b2 where b2.bookid=b1.bookid and b2.bookcate="低学年向け" limit 1)

)

group by bookid

◎質問者からの返答

あ、はい。わかりました。。。


3 ● sato_hyper
●40ポイント

同じbookid内でbookcateが重複しないのであれば下記で抽出できると思います。

select * from bookinfo as b1

where

( select count(*) from bookinfo as b2 where b1.bookid = b2.bookid and

( b2.bookcate="絵本" or b2.bookcate="学習" or b2.bookcate="低学年向け")

) = 3

◎質問者からの返答

おぉ!まさにこんな感じのを求めていました。ありがとうございます。

もう少し効率のよい方法があるか待ってみます。

ありがとうございました。


4 ● kurukuru-neko
●15ポイント

MYSQL 5.0以上が前提で少し反則気味ですが。

select booktitle,bookid,bit_or(
 case bookcate 
 when "絵本" then (1<<0) 
 when "学習" then (1<<1)
 when "低学年向け" then (1<<2) 
 else 0 
 end
) as bits 
from bookinfo group by bookid having bits=b'111';

又は
from bookinfo group by bookid having bit_count(bits)=3 
でもよい
◎質問者からの返答

大変貴重なご回答ありがとうございます。


5 ● kurukuru-neko
●20ポイント ベストアンサー

> when "絵本" then (1<<0)

> when "学習" then (1<<1)

> when "低学年向け" then (1<<2)

>この数字は検索カテゴリが増えるに従ってどのよう>につけていけばいいのでしょうか?

カテゴリーの数ではなく whenに書いた順番

なので10進数で書くと

when "絵本" then 1

when "学習" then 2

when "低xx" then 4

のように2倍した数字を順にかくだけです。

(2倍するのは、2進数で桁上げをさせる為)

カテゴリーを特定の数値に固定する必要は

ありません。

項目がwhenに一致しない場合はelseの0

となり0となります。

bitsの値は、各whenで一致した項目の

数値を足したものになります。

全部一致する場合は

7 = 1 + 2 + 4

(2進数では111)

bit_orは2進数で論理演算する機能

です。

1を2進数で表現すると 1

2を2進数で表現すると 10

4を2進数で表現すると100

のように順に0が増えます。

bit_orは上記内容の各桁の論理和を

計算します。

論理は

0と0 -> 0

1と0,0と1,1と1 -> 1

となります。

上記1,10、100を各桁で

論理和すると

   1
    10
  100
 =====
  111

となります。

カテゴリー64個以下で済むなら

はじめからカテゴリーを数値かして

保存しておいた方処理も早く出来る。

http://dev.mysql.com/doc/refman/4.1/en/group-by-functions.html

◎質問者からの返答

回答ありがとうございます。

早速試してみたいと思います。本当にありがとうございました。

関連質問


●質問をもっと探す●



0.人力検索はてなトップ
8.このページを友達に紹介
9.このページの先頭へ
対応機種一覧
お問い合わせ
ヘルプ/お知らせ
ログイン
無料ユーザー登録
はてなトップ