• 締切済み

カテゴリに紐づいているサブカテゴリを取得するには

SQLで質問があります。 カテゴリテーブルがあります。 カテゴリテーブルのフィールドは以下の通りです。  ・カテゴリコード  ・カテゴリ名  ・親コード 例えば下記のようなデータとします。 1000|洋服  |NULL 1100|子供服 |1000 1110|ズボン |1100 1111|半ズボン|1110 1112|長ズボン|1110 1120|シャツ |1100 1121|Tシャツ|1120 1200|婦人服 |1000 1300|男性服 |1000      ・      ・      ・      ・ カテゴリはプルダウンで 洋服(1000)      →子供服(1100)           →子供服(1100)                →長ズボン(1111) の順に選択しました。 「カテゴリ」のプルダウンを選択すると選択したカテゴリに紐づいている「サブカテゴリ」のプルダウンを順々に表示しています。 データベースに登録されているカテゴリコードは最後に選択した「長ズボン」の「1111」です。 この場合、SQLで「長ズボン」の「1111」をキーにして「洋服(1000)」「子供服(1100)」「子供服(1100)」というカテゴリを取得するにはどのように記述したらいいのでしょうか。 説明、下手ですみませんが理解していただけましたでしょうか。 申し訳ありませんがアドバイス、宜しくお願いします。 あ、データベースはpostgreSQL8.4.9です。 では、失礼します。

みんなの回答

  • Siegrune
  • ベストアンサー率35% (316/895)
回答No.3

1111の親を全部探すというのは、再帰SQLを使えばつくるのは簡単にできるのですが・・・。 http://lets.postgresql.jp/documents/technical/with_recursive の 再帰SQL (WITH RECURSIVE) にあるサンプルの tree.parent = r.id を tree.child = r.id にするという話。 ただし、登録ミスした内容によっては無限ループして異常終了するとか 別なところで問題はあります。 テーブル設計については、親子で表現するのではなく、 大分類コード 中分類コード 小分類コード ・・・ とそれぞれ持たせるほうがシンプルでわかりやすいとは思いますが。 (実際に子供服の売上を集計したいときとかに不自由なコード系になってしまいます。  ・・・値の桁位置が大分類/中分類/・・・と意味を持っているなら別ですが、  0~9で足りなくなってABC・・・と増えていくのは考え物ですし。)

nanchatte_se
質問者

お礼

ストアドプロシージャでいい感じまできたのでストアドプロシージャで取得する方向で進めたいと思います。 皆さん、貴重な意見、またアドバイス、本当にありがとうございました。

nanchatte_se
質問者

補足

返答が遅くなってすみません。 アドバイス、ありがとうございます。 なぜこのようにしたかというと大分類、中分類、小分類以上にカテゴリが細かく設定できるようにしているみたいです。 なので仕様というか、テーブル構造は変更できません。 貴重なご意見、本当にありがとうございます。

  • wipe3out
  • ベストアンサー率0% (0/0)
回答No.2

すみません、上で回答したものです。 回答に紛らわしい部分があったので訂正です。 参考URLで紹介した方法ですが、質問者様のテーブル構造だとだめっぽいです。 前に見た覚えがあったので紹介したのですが、ちゃんと確認してませんでした。。。 多分、以下のようなテーブル構造を前提とした記事になっています。 カテゴリ名、コード最小値、コード最大値 洋服、1000、1399 子供服、1100、1199 ズボン、1110、1119 半ズボン、1111、1111 (略) 婦人服、1200、1299 上記の構造だと、子供服以下のノードを列挙したい場合、「子供服行のコード最小値以上、コード最大値以下」という条件でSELECTすれば、子ノードがずらっと取れます。 質問のように逆をやりたい場合、半ズボンのコードが「コード最大値」、「コード最小値」の間に含まれるという条件でSELECTすれば、やはり親ノードがずらっと取れます。適当ですが以下に参考のコードを書きます。 SELECT * FROM TABLE WHERE コード最小値 <= 1111 AND コード最大値 >= 1111 テーブル設計が変更可能なら、参考URLを確認して、上記のような構造にするほうが後々何かと楽かとおもいますよ~

nanchatte_se
質問者

お礼

ストアドプロシージャでいい感じまできたのでストアドプロシージャで取得する方向で進めたいと思います。 皆さん、貴重な意見、またアドバイス、本当にありがとうございました。

nanchatte_se
質問者

補足

返事が遅くなってすみません。 下記の「子供服(1100)」「子供服(1100)」の箇所は誤りです。大変、申し訳ありませんでした。 > ただ、質問文だと「洋服(1000)」「子供服(1100)」「子供服(1100)」のように「子供服」を重複して抽出しているようなのですが、これは誤記でしょうか??それとも何か意味があるのでしょうか?この辺、重要なら詳しく書いたほうがいいかもです。 一応、試行錯誤してストアドプロシージャでカテゴリコードをキーにして親コードを取得。親コードがNULLになるまで繰り返してSQL文を生成して何とか取得する事ができましたが・・・

  • wipe3out
  • ベストアンサー率0% (0/0)
回答No.1

SQLに関しては初心者なので、的外れかもしれませんが、解法を思いついたので投稿します。 1.コードで探す。 上記のサンプルが実物と違うかもしれないので、なんともいえないのですが、コードを使って絞ればよいのではないでしょうか??上記のコード体系の性質が実物と同じなら、1111というコードを末尾から0に置き換えて行けば親カテゴリのコードである1000、1100、1110が取得できるので、後は単純にSELECTを使って抽出すれば良い気がします。コードは(適当ですが)以下のような感じです。 SELECT * FROM TABLE WHERE code = IN(1000, 1100, 1110) たとえば、「ネクタイ(1310)」というのがあれば、末尾が0なので、これは三番目の階層ですよね。なので、三桁目から順に0に置き換えたコード1000、1300が親カテゴリのコードになります。これでSELECTすればいい気がします。 ただ、質問文だと「洋服(1000)」「子供服(1100)」「子供服(1100)」のように「子供服」を重複して抽出しているようなのですが、これは誤記でしょうか??それとも何か意味があるのでしょうか?この辺、重要なら詳しく書いたほうがいいかもです。 また、コードのトリックが使えない場合に関しては、参考URLの「2-7.パスを列挙する(列持ちバージョン)」、「2-6.部分木を列挙する」を応用すれば出来ると思います。参考サイトはとても勉強になるので、暇なときに一通り読むと幸せになれるかもしれません。 がんばってください!

参考URL:
http://www.geocities.jp/mickindex/database/db_tree_ns.html#LocalLink-intro

関連するQ&A

  • カテゴリー商品の前後ページを取得する方法

    あるカテゴリーの商品詳細ページで前後詳細ページへのリンクを設けたいのですが、 後ろページの取得は上手くいきますが、前のページの取得がうまくいきません。 カテゴリーと商品は別テーブルで関連付けテーブルで紐づけさせてます。 PHP+MySQLで構築中です。 ・カテゴリー関連付けテーブル(catgory_term) --------------- | category_id | id | --------------- ・商品テーブルテーブル(items) ----------------------- | id | title | url | ・・・・・・・・・ ----------------------- SQL文は下記のような感じです。(並び順でもSQL内容は変わります.。下記の例は商品ID降順) SELECT items.title,items.id,items.url,MIN(items.id) FROM category_term Left JOIN items ON category_term.id = items.id WHERE category_term.category_id = 'カテゴリーID' AND items.status = 'publish' AND items.id > '商品ID' お手数をおかけしますがご教授いただける幸いです。

    • ベストアンサー
    • MySQL
  • SQL文の記述について

    以下の項目を抽出するSQL文を色々考えているの ですが、どうしても思い浮かびません。ぜひとも ご教示いただきたく存じます。使用データベースは PostgreSQL7.2です。 テーブル構成は以下のとおりです。 事業コード 部署コード 情報コード 01     02     01 01     02     02 01     02     03 02     05     01 02     05     02 02     05     05 02     07     02 02     07     03 02     07     06 以上のようなテーブルから、「情報コード02と03の 両方をもつ事業コードと部署コードの組み合わせ」を 求めるSQLを記述したいのです。この結果は 事業コード 部署コード 01     02 02     07 となります。 以上のような説明でご理解いただけますでしょうか。 足りない情報などがありましたらご指摘ください ませ。 宜しくお願いいたします。

  • 条件分岐について

    いつもお世話になっています。 クラシックなASPを使ってwebプログラミングに挑戦しています。 すみませんが条件分岐について教えてください。 カテゴリとサブカテゴリがあります。 カテゴリ1を選択したときには、サブカテゴリに1に紐づくものを、 同様にカテゴリ2のときにはサブカテゴリには2に紐づくものだけを 表示させたいです。 で、自分で考えたのが以下です。 ------------------------------ <select name="category2"> Select Case <%= rs("category") %> Case "A" <option value="<%= rs("category2") %>"><%= rs("category2") %></option> <option value="01">01</option> <option value="02">02</option> <option value="03">03</option> <option value="04">04</option> Case "B" <option value="<%= rs("category2") %>"><%= rs("category2") %></option> <option value="05">05</option> <option value="06">06</option> <option value="07">07</option> Case Else <%= rs("category2") %>"><%= rs("category2") %> End Select -------------------------------------- で、こうやると、caseの条件が無視されて、全部がプルダウンに 表示されてしまいます。 自分ではどうにも解決の糸口がみつからないので、なぜできないのか、 どうすればできるのか、教えていただけないでしょうか。 よろしくお願いします。

  • LIKEについてです。

    こんばんわ。プログラミング、データベース初心者です。 皆さんにどうしても教えて欲しいSQL文があります。 テーブルが3つあったとして、 1つはカラムに市町村のコードと名前が入ってるテーブルA、 2つめはカラムに色々なジャンルのコードと名前が入ってるテーブルB、 そして3つめにそれらのコードのみが入っていて、 色々カラムに他の情報が入ってる実際に使いたいテーブルCがあります。 例えば市町村名や町域で検索をかけた場合、 それを変数に入れて、 テーブルAでwhere句にてLIKE検索してコードを取り、 そのコードで紐づいたテーブルCからの情報を全部取りたいです。 一度に済ますにはどのようにSQLを書けばいいのでしょうか? 色々調べてみたのですが、全然わかりません。 回答いただけると大変ありがたいです。 よろしくお願いします。

    • ベストアンサー
    • MySQL
  • ストアド内で実行したSQLの出力結果について

    現在、引数の値を元に下記のようなSQL文を生成しています。 SELECT code, name FROM T_CGY WHERE code = '1111' UNION SELECT code, name FROM T_CGY WHERE code = '1110' UNION SELECT code, name FROM T_CGY WHERE code = '1100' UNION SELECT code, name FROM T_CGY WHERE code = '1000' ORDER BY code; ※出力されたSQL文に誤りがないかを確認する為にコピーしてターミナル上で実行したら該当するレコードを取得する事ができました。 それをストアドプロシージャ内で生成したSQL文を「QUERY EXECUTE」を実行して該当するレコードが取得できるように改造してみました。 下記が出力された結果です。 getCgyData -------------------- (1000,洋服) (1100,子供服) (1110,ズボン) (1111,長ズボン) 出力されたデータは私が望んだ内容なんですが・・・ 私的には下記のように出力したいと考えています。 col1    | col2 ------------------------- 1000  | 洋服 1100  | 子供服 1110  | ズボン 1111  | 長ズボン 何とか上記のように出力できるようにするにはどうしたらいいでしょうしょうか。 そもそも上記のように出力する事は可能なのでしょうか。 CREATE FUNCTION getCgyData (VARCHAR) RETURNS TABLE(col1 VARCHAR, col2 VARCHAR) AS ' DECLARE key ALIAS FOR $1; sql TEXT; BEGIN                 ・                 ・ ※ここでSQL文を生成して、変数(sql)に格納しています。                 ・                 ・ RETURN QUERY EXECUTE sql; END; ' language 'plpgsql' ; データベースのバージョンはpostgreSQL8.4.9です。 再度、申し訳ありませんがアドバイス、宜しくお願いします。 では、失礼します。

  • MySQLとPostgreSQLについてのSQLインジェクション

    はじめて質問させていただきます。 よろしくお願いします。 現在、私は大学の研究テーマでデータベース(MySQL、PostgreSQL)を使っているCGIを自作し、それぞれのデータベースについてSQLインジェクションの脆弱性について調べる、という研究を行っています。 ブラインドSQLインジェクションについて調べているのですが、 PostgreSQLの場合、pg_tablesというテーブルにデータベースのテーブル一覧表がのっていて、それを参照することでテーブル名が取得でき、いろいろ悪いことができてしまいますが、MySQLの場合、ブラインドSQLインジェクションを起こそうと思った場合どのようなコマンドを使えばよいのでしょうか? SHOW TABLESで使用中のデータベースのテーブル一覧は取得できますが、それをクエリの一部として使うことはできるのでしょうか・・・? また、全く関係ない質問なのですが、このCGIはRubyで記述して作りました。Rubyにはプリペアドステートメントという機能があるのですが、これをデータベースにアクセスするすべての箇所で用いればSQLインジェクションは100%起きないといえるのでしょうか?(現在考え得る範囲でよいのでお願いします) 卒論で困っているので知っている方がおられましたらどうかよろしくお願いいたします。

  • postgreSQLでテーブルの一覧

    他人が管理していたUNIXマシンのデータベースがあります。 postgreSQLです。 さて、SQLコマンドで、SELECTとかINSERTとかはわかった(というか 教わった)のですが・・・・ テーブルが複数あるようなので、そのテーブルの一覧というか、 すべてのテーブルの名称を見るにはどうしたらよいのでしょうか?

  • プルダウンで選択すると、DBの値を取得したい

    いつもお世話になっております。 プログラム初心者ですが、どうしても方法がわからないので質問させていただきます。 サーバー側 ASP(VBS) クライアント側 html javascriptで作成しているのですが、 プルダウンを選択すると、そのテーブルの列にある値をテキストボックスにいれたいと思っています。 例えば、以下のようなテーブルがあって、 法人コード | 会社コード | 法人名 ------------------------------    1    |   aa    | トヨタ ------------------------------    2    |   bb    | ニッサン ------------------------------    3    |   cc    | ホンダ データベースから読み込んで、法人コードをプルダウンにセットします。 プルダウンが選択されると、その列の会社コードと法人名をテキストエリアに出力したいと思います。 ※例 法人コード「1」をプルダウンで選択すると、「aa」と「トヨタ」がテキストエリアに表示される。 連動プルダウンで、直接option value部分に書けばできそうですが、 データの量が膨大な為、直接コードに書くのは難しそうです。 form action で、1度別のベージに飛ばして、 そこで、SQL文にて、法人コードを条件にして出力しようともしましたが、 全体がformで囲まれているので、formの入れ子になりできませんでした。 おそらくjavascriptで、select部分で、onchange="Selc(this)"とすれば、 その処理を行うと思うのですが、処理自体の書き方がわかりません。 プルダウン部分に法人コード一覧を表示させることは、できましたが、 その後の処理の書き方がわかりませんので、 ご存知の方がいらっしゃいましたら、ご回答宜しくお願いします。 一部ソースを載せます。 <% ' データベース接続の確立 Set Conn = ConnectDB(DSN) ' 法人マスタテーブルから値を取得 SQL = "Select 法人コード,会社コード,法人名称 From 法人マスタ ORDER BY 法人コード" Set Rs = ExecSql(Conn, SQL) %> <tr class="example"> <td style="width:300px; text-align:left; background-color: #00ff00;"> <b>法人コード</b> </td> <td> <select name = "houjin"> <option value=""/>--------法人コード選択--------</option> <% While Not Rs.EOF Response.Write"<option value=""" & Rs("法人コード") & """>" & Rs("法人コード") & " " & "</option>" Rs.MoveNext Wend %> </select> </td> </tr> <tr class="example"> <td style="width:300px; text-align:left; background-color: #00ff00;"> <b>会社コード</b> </td> <td> <textarea name="kaisya" style="width:100%" rows=1 class="textbox"></textarea> </td> </tr> <tr class="example"> <td style="width:300px; text-align:left; background-color: #00ff00;"> <b>法人名</b> </td> <td> <textarea name="hmei" style="width:100%" rows=1 class="textbox"></textarea> </td> </tr> どうぞよろしくお願いします。

  • すでにあるsqlファイルを使用して、データベースを作成する方法

    すでにあるsqlファイルを使用して、データベースを作成する方法 もらったシステム(html,php,sqlで構成されるシステム)を自分の環境で動かそうとしているのですが、データベースを作成できないため、先に進むことが出来ず困っています。 もらったシステムには、テーブルのsqlファイルや、そのテーブルに入れるデータのsqlファイルがありました。 わかりにくい文章ですいません。 どなたかご存じの方、ご教授お願いいたします。 OS: CentOS5.3 postgresql8.1.18 apache2.2.3 php5.1.6

  • シーケンスのリストを取得したい。

    いつもお世話になっております。 インターネットサーバー上のPHPから postgreSQLのデータベース内の テーブル名とシーケンス名のリストを SELECTを使ったSQL文にて取得したいのです。 テーブルリストは、 select * from pg_tables where not tablename like 'pg%' order by tablename; で取得できましたが、 シーケンス名のやり方がわかりません。 phppgadminでシーケンスの表が表示できるので、 phpでも出来ると思うのですがわかりません。 お知恵をおかしください。 hiroko