PHPのコーディングで悩んでいることがあります。

DBに、1・メンバーTB、2・カテゴリーTB、3・サブカテゴリTBで登録するわけですが、今後仕様変更に対する柔軟性から、テーブル設計はT字型ER手法を考えています。
つまり、4・メンバーTOカテTOサブカテのTBが一つ増えるわけです。
メンバーは全てのカテゴリに登録しません。
サブカテゴリの項目が10あったとします。メンバーが登録するのは3つかもしれません。不確定です。

そこで、ある特定のメンバーがどのサブカテゴリに属しているのか?調べようとした際、属していないサブカテゴリの項目にはfalseを返したいのです。
どのようなことかといいますと、サイトにメンバーでログインした場合、会員専用ページでサブカテゴリを列挙し『あなたはこのサブカテゴリは未登録です。このサブカテゴリに登録しますか?』また、『あなたはこのサブカテゴリは登録済です。サブカテゴリ情報を更新しますか?』みたいなことをPHPで行いたいのです。

私が、関数に弱いので応用がきかないのだと思います。何かいいアイデアはありませんか?
使用環境はPHP5、MySQLです。

回答の条件
  • 1人10回まで
  • 登録:2007/03/25 06:32:17
  • 終了:2007/03/26 05:14:15

ベストアンサー

id:nandedarou No.2

nandedarou回答回数230ベストアンサー獲得回数342007/03/26 03:14:40

ポイント100pt

1.

カテゴリTBの全フィールドと全レコードをデータベースから読み出し、

例えば、echo "$Cat[1]$,Cat[2]$,Cat[3]"; で、「アウトドアスポーツ,園芸,建設機器」と表示されるように、連想配列 $Cat に保存して下さい。


2.

サブカテゴリTBの全フィールドと全レコードをデータベースから読み出し、

例えば、echo "$SubCat[1],$SubCat[2],$SubCat[3]"; で、「スクール,販売,レンタル」と表示されるように、連想配列 $SubCat に保存して下さい。


※1.と2.のやり方わかりますよね?分からなかったら、聞いて下さい。


3.

メンバーの山田さん(メンバーID:1)は、アウトドアスポーツ(カテゴリID:1)の販売(サブカテゴリID:2)と園芸(カテゴリID:2)のレンタル(サブカテゴリID:3)を行っている場合、以下のようになります。


メンバーtoカテtoサブカテTB

メンバーID(PK)、カテゴリID(PK)、サブカテゴリID(PK)

1,1,2

1,2,3


4.

あるカテゴリーとあるサブカテゴリーが組合せ可能かどうかの情報が必要ですので、次のテーブルを追加して下さい。

※これは、メンバー専用画面の表示項目となります。

カテtoサブカテTB

カテゴリID、サブカテゴリID

1,1

1,2

2,1

2,3

3,2

3,3


5.

この状態で、次のSQLを実行して下さい。

SELECT   A.カテゴリID, A.サブカテゴリID, B.サブカテゴリID IS NOT NULL as 登録
FROM     カテtoサブカテTB AS A  LEFT JOIN  メンバーtoカテtoサブカテTB AS B
ON       A.カテゴリID = B.カテゴリID  AND  A.サブカテゴリID = B.サブカテゴリID
AND      B.メンバーID = '1'
ORDER BY A.カテゴリID, A.サブカテゴリID
;

※ AND B.メンバーID = '1' の部分は、もちろん、中島さんならば、AND B.メンバーID = '2' として下さい。


結果は次のようになります。


カテゴリID,サブカテゴリID,登録

1,1,0

1,2,1

2,1,0

2,3,1

3,2,0

3,3,0


※登録フィールドに1が入っていれば、登録済みです。

※登録フィールドに0が入っていれば、未登録です。


6.

あとは、簡単です。

5.の結果のデータを $Cat と $SubCat でカテゴリー名とサブカテゴリー名に直して表示し、

登録が1ならば、「(登録されています。登録内容を更新しますか?削除しますか?)」

登録が0ならば、「(未登録です。登録しますか?)」

と表示すればいいでしょう。


以上、いかがでしょうか?

id:seadwell

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

さらには、コメントを2つも頂きお気遣いありがとうございます。


いや~、すばらし過ぎます。ズバリそのものです。

参りましたm(_ _)m。感謝感激です!

こんなに複雑な構造を、よく整理できますね・・・。

初めて、SQL文の理解に触れられたような気がしました。


みそは、回答4.のカテtoサブカテTBですね。

やはり、私の設計に問題があるようした^^;

現在、SELECT文で[IS NOT NULL as 登録]の部分がはじめて見る構文なので、一生懸命調べていました。

とりあえず、IS NOT NULL as 登録を除いては理解できますので、この質問は終了いたします。


kato-sさまは圧倒的な情報不足から返答してくださったので、このすばらしい回答も得ることができたのだと、kato-sさまにも感謝します。

質問の500文字は何とかなりませんかね・・・。

回答者に余計な手間と、質問推測に余計な労力を掛けてしまいます><。

2007/03/26 05:11:34

その他の回答(1件)

id:kato-s No.1

kato-s回答回数91ベストアンサー獲得回数32007/03/25 09:59:23

ポイント35pt

PHPからMYSQLに対してSQLの実行方法をご存じと仮定した場合ですが、


select count(*) as result from サブカテゴリTB a

inner join サブカテゴリTO b

on a.サブカテゴリコード = b.サブカテゴリコード

where b.メンバーコード=xxx and b.サブカテゴリコード=xxx


のようなSQLを実行して、resultが0の場合whereで指定したメンバーは、

whereで指定したサブカテゴリには登録されていないということになります。

※テーブルの項目定義がわからないのでもしかするとサブカテゴリTOも

where条件に入れる必要があるかも知れませんが…。


※もしPHPからMYSQLに対してSQLの実行方法がわからない場合は以下が参考になります。

http://www.atmarkit.co.jp/flinux/rensai/mysql05/mysql05b.html

id:seadwell

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

質問が500文字に限定されていることから、漠然とした質問なってしまったのに、内容を推測くださってありがとうございます。

具体的な例を示してくださったのに、SQLの実行方法は理解しているのですが、私のスキル不足で応用できずにいます。

2度手間になると思うのですが、もう少しお付き合いお願いできませんか?

(1)メンバーTB

メンバーID(PK)、メンバー氏名

1,山田

2,中島

3,田中

(2)カテゴリTB

カテゴリID(PK)、カテゴリ名

1,アウトドアスポーツ

2,園芸

3,建設機器

(3)サブカテゴリTB

サブカテゴリID(PK)、サブカテゴリ名

1,スクール

2,販売

3,レンタル

(4)メンバーtoカテtoサブカテTB

メンバーID(PK)、カテゴリID(PK)、サブカテゴリID(PK)


メンバーの山田さんは、アウトドアスポーツの販売と園芸のレンタルを行っています。

後に、園芸のスクールも始めようと考えています。


[メンバー専用画面]

アウトドアスポーツ

スクール(未登録です。登録しますか?)

販売(登録されています。登録内容を更新しますか?削除しますか?)

園芸

スクール(未登録です。登録しますか?)

レンタル(登録されています。登録内容を更新しますか?削除しますか?)

建設機器

販売(未登録です。登録しますか?)

レンタル(未登録です。登録しますか?)


以上、メンバー専用画面では(4)メンバーtoカテtoサブカテTB に判断させようと考えています。

(4)のTBは、メンバー専用画面ばかりでなく、他の抽出処理にも使います。

サブカテゴリTBのレコードでスクールなどの内容はカテゴリに応じてフォーマットが違いますので、アウトドアスクールTBと園芸スクールTBを別に設けます。

当然、そこには(2)カテゴリTB、および、(3)サブカテゴリTBと、アウトドアスクールTBや園芸スクールTB対応するT字型ER手法を設ける必要があると考えています。

ここでの質問は、『未登録です』もしくは『登録されています』の処理を分岐させるには?という質問なのですが、内部結合を行いカウントを取りにいけばどうなるか?が今一理解できずにいます。スミマセン><。

もしかして、for文でループしフラグを立てるということでしょうか?

そもそも、私がやらせたいことにTB設計自体が間違っているのかもしれません。

根本的なTB設計も含め、もう一度回答をいただければ幸いです。

2007/03/25 22:18:34
id:nandedarou No.2

nandedarou回答回数230ベストアンサー獲得回数342007/03/26 03:14:40ここでベストアンサー

ポイント100pt

1.

カテゴリTBの全フィールドと全レコードをデータベースから読み出し、

例えば、echo "$Cat[1]$,Cat[2]$,Cat[3]"; で、「アウトドアスポーツ,園芸,建設機器」と表示されるように、連想配列 $Cat に保存して下さい。


2.

サブカテゴリTBの全フィールドと全レコードをデータベースから読み出し、

例えば、echo "$SubCat[1],$SubCat[2],$SubCat[3]"; で、「スクール,販売,レンタル」と表示されるように、連想配列 $SubCat に保存して下さい。


※1.と2.のやり方わかりますよね?分からなかったら、聞いて下さい。


3.

メンバーの山田さん(メンバーID:1)は、アウトドアスポーツ(カテゴリID:1)の販売(サブカテゴリID:2)と園芸(カテゴリID:2)のレンタル(サブカテゴリID:3)を行っている場合、以下のようになります。


メンバーtoカテtoサブカテTB

メンバーID(PK)、カテゴリID(PK)、サブカテゴリID(PK)

1,1,2

1,2,3


4.

あるカテゴリーとあるサブカテゴリーが組合せ可能かどうかの情報が必要ですので、次のテーブルを追加して下さい。

※これは、メンバー専用画面の表示項目となります。

カテtoサブカテTB

カテゴリID、サブカテゴリID

1,1

1,2

2,1

2,3

3,2

3,3


5.

この状態で、次のSQLを実行して下さい。

SELECT   A.カテゴリID, A.サブカテゴリID, B.サブカテゴリID IS NOT NULL as 登録
FROM     カテtoサブカテTB AS A  LEFT JOIN  メンバーtoカテtoサブカテTB AS B
ON       A.カテゴリID = B.カテゴリID  AND  A.サブカテゴリID = B.サブカテゴリID
AND      B.メンバーID = '1'
ORDER BY A.カテゴリID, A.サブカテゴリID
;

※ AND B.メンバーID = '1' の部分は、もちろん、中島さんならば、AND B.メンバーID = '2' として下さい。


結果は次のようになります。


カテゴリID,サブカテゴリID,登録

1,1,0

1,2,1

2,1,0

2,3,1

3,2,0

3,3,0


※登録フィールドに1が入っていれば、登録済みです。

※登録フィールドに0が入っていれば、未登録です。


6.

あとは、簡単です。

5.の結果のデータを $Cat と $SubCat でカテゴリー名とサブカテゴリー名に直して表示し、

登録が1ならば、「(登録されています。登録内容を更新しますか?削除しますか?)」

登録が0ならば、「(未登録です。登録しますか?)」

と表示すればいいでしょう。


以上、いかがでしょうか?

id:seadwell

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

さらには、コメントを2つも頂きお気遣いありがとうございます。


いや~、すばらし過ぎます。ズバリそのものです。

参りましたm(_ _)m。感謝感激です!

こんなに複雑な構造を、よく整理できますね・・・。

初めて、SQL文の理解に触れられたような気がしました。


みそは、回答4.のカテtoサブカテTBですね。

やはり、私の設計に問題があるようした^^;

現在、SELECT文で[IS NOT NULL as 登録]の部分がはじめて見る構文なので、一生懸命調べていました。

とりあえず、IS NOT NULL as 登録を除いては理解できますので、この質問は終了いたします。


kato-sさまは圧倒的な情報不足から返答してくださったので、このすばらしい回答も得ることができたのだと、kato-sさまにも感謝します。

質問の500文字は何とかなりませんかね・・・。

回答者に余計な手間と、質問推測に余計な労力を掛けてしまいます><。

2007/03/26 05:11:34
  • id:nandedarou
    6.は、foreachによるループ処理 で5.のデータをすべて表示するとよいでしょう。
    ※必要でしたら、お答えいたしますので、聞いて下さい。
  • id:nandedarou
    いるかありがとうございました!

    ちょっと説明します。

    値がセットされないと、データベースは、NULL値を返します。

    「B.サブカテゴリID IS NOT NULL」は、
    テーブルBのサブカテゴリIDがNULLならば、ture(1)。そうでなければ、false(0)になります。

    「SELECT ~ as 登録」は、
    結果レコード上に、新たに「登録」というフィールドをつくり、~の値を返すということです。

    他の質問者の方で、質問後すぐに「この質問・回答へのコメント」で、質問の補足をしている人がいました。次回質問時に、試してみて下さい。
  • id:nandedarou
    上記コメントで、一部誤記がありました。以下のとおり訂正します。

    「B.サブカテゴリID IS NULL」は、
    テーブルBのサブカテゴリIDがNULLならば、true(1)。そうでなければ、false(0)になります。

    「B.サブカテゴリID IS NOT NULL」は、上記のNOT(否定)なので、逆の結果です。
    テーブルBのサブカテゴリIDがNULLならば、false(0)。そうでなければ、true(1)になります。
  • id:seadwell
    こんにちは、アフターフォローのコメントまで何から何までありがとうございました。


    > 「SELECT ~ as 登録」は、
    > 結果レコード上に、新たに「登録」というフィールドをつくり、~の値を返すということです。

    なんか、勝手にフィールドを作ってくれるのだろ~な~・・・。と思い、教えていただいたSQL文をダミーデータで実行させ、無事動作確認まで取れました。
    ほんとに感謝するばかりですm(_ _)mありがとうございました。


    > 他の質問者の方で、質問後すぐに「この質問・回答へのコメント」で、質問の補足をしている人がいました。次回質問時に、試してみて下さい。

    なるほど・・・。コメントで補足するとは考えもつきませんでした。
    次回から試してみます^^
  • id:nandedarou
    kurukuru-neko 様から、よりよいSQLの書き方を教えて頂きました。次のSQLを実行することにより、カテゴリ名とサブカテゴリ名入りの結果テーブルを取得できます。(kurukuru-neko 様ありがとうございました。)

    SELECT A.カテゴリID, カテゴリ名, A.サブカテゴリID, サブカテゴリ名, IF(メンバーID IS NULL,0,1) as 登録
    FROM カテtoサブカテTB AS A
    LEFT JOIN カテゴリTB USING(カテゴリID )
    LEFT JOIN サブカテゴリTB USING(サブカテゴリID)
    LEFT JOIN メンバーtoカテtoサブカテTB AS B
    ON A.カテゴリID = B.カテゴリID AND A.サブカテゴリID = B.サブカテゴリID AND B.メンバーID = '1'
    ORDER BY A.カテゴリID, A.サブカテゴリID
    ;

この質問への反応(ブックマークコメント)

「あの人に答えてほしい」「この質問はあの人が答えられそう」というときに、回答リクエストを送ってみてましょう。

これ以上回答リクエストを送信することはできません。制限について

絞り込み :
はてなココの「ともだち」を表示します。
回答リクエストを送信したユーザーはいません