質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
PostgreSQL

PostgreSQLはオープンソースのオブジェクトリレーショナルデータベース管理システムです。 Oracle Databaseで使われるPL/SQLを参考に実装されたビルトイン言語で、Windows、 Mac、Linux、UNIX、MSなどいくつものプラットフォームに対応しています。

データベース

データベースとは、データの集合体を指します。また、そのデータの集合体の共用を可能にするシステムの意味を含めます

データベース設計

データベース設計はデータベースの論理的や物理的な部分を特定する工程です。

Q&A

5回答

627閲覧

ある列の値によって、他の列の値の候補が絞られる場合のテーブル設計について

7Kreuz

総合スコア112

PostgreSQL

PostgreSQLはオープンソースのオブジェクトリレーショナルデータベース管理システムです。 Oracle Databaseで使われるPL/SQLを参考に実装されたビルトイン言語で、Windows、 Mac、Linux、UNIX、MSなどいくつものプラットフォームに対応しています。

データベース

データベースとは、データの集合体を指します。また、そのデータの集合体の共用を可能にするシステムの意味を含めます

データベース設計

データベース設計はデータベースの論理的や物理的な部分を特定する工程です。

0グッド

0クリップ

投稿2019/02/28 07:00

前提・実現したいこと

現在、企業の発注履歴(どういうものを購入したか)を管理するデータベースをPostgreSQLで作成しております。
発注情報として、「商品」「発注先」「(その発注先における)担当者」があります(実際はもっと項目は多いですが)。
次のイメージです。

発注ID商品発注先担当者
1ペン文具屋鈴木
2寝具屋佐藤
3マウス電気屋
4鉛筆文具屋佐藤
5消しゴム文具屋
6ペンなんでも屋

注文2の担当者である「寝具屋の佐藤」と、注文4の担当者である「文具屋の佐藤」は、名前が同じだけの別人です。また、担当者は空欄(不明)であることもあります(実際は、半分以上が空欄です)。
そこで、次のようにテーブルを作成しました。

商品テーブル↓

id名前
1ペン
2
3マウス
4鉛筆
5消しゴム

発注先テーブル↓

id名前
1文具屋
2寝具屋
3電気屋
4なんでも屋

担当者テーブル↓

id所属(発注先)名前
11鈴木
21佐藤
32佐藤

発注テーブル↓

発注ID商品発注先担当者
1111
2223
3330
4412
5510
6140

これらを結合すれば、冒頭の表を表現することができます。

発生している問題

問題としては、発注テーブルに、「発注先2、担当者1」といった、存在しない「発注先と担当者の組」を入力できてしまうことです。プログラム側ではもちろんチェックをしますが、データベース側でも制約を設けたいです。そもそもデータが冗長になっているので、うまい設計方法や、そのためのヒントをご教示いただけると幸いです。

調べたこと

CHECK制約→制約の中で他のテーブルを参照する方法がわからず断念
外部キー制約→複数の列に対して設定する方法がわからず断念

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答5

0

発注先の人事を管理するわけじゃないんですから、発注先テーブルに担当者のカラムを持つべきです。
発注先の電話番号等と同じような、属性情報として扱わないと面倒です。

発注テーブルに発注先の担当者を持たせたいなら、発注先を選択時に発注先のテーブルから取得して初期値として設定し、変更可能にしておくとかじゃないでしょうか。

投稿2019/02/28 07:26

編集2019/02/28 08:02
sazi

総合スコア25195

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

maisumakun

2019/02/28 07:30

同じ発注先で担当者複数、という場合が示されていますが、それはどのようにハンドリングしますか?
7Kreuz

2019/02/28 07:32

なるほど 1つの発注先に複数の担当者が存在する場合があるのですが(文具屋には佐藤と鈴木がいる)、そのようなときはどうするのが適当でしょうか?
sazi

2019/02/28 07:39 編集

メモ欄と同じような扱いで内容はフリーで良いと思います。 先方の担当者で検索するような用途も想定しにくいし、別テーブルで管理するメリットを感じませんし、 厳密に管理されるような項目ではないから、リンク切れのような不備が発生してもリカバリできなくなる可能性が大だと思います。
sazi

2019/03/01 01:01

また、担当者のテーブルを設ける場合に、発注テーブルで選択すべき担当者が複数いる場合、担当者を選択するって事になりますよ? 要件で要求されているなら別ですけど、発注に関して担当者を管理してまで明確な事が重要だとは思えないのですが。
7Kreuz

2019/03/02 05:46

要件まで踏み込んだご回答、ありがとうございます。 >先方の担当者で検索するような用途 これは確かになさそうです。 >発注テーブルで選択すべき担当者が複数いる場合、担当者を選択する これはまさにそうで、そのようにしようと考えています。 アプリケーション側で、発注先に文具屋が選択されている状態で担当者欄を入力しようとすると、「佐藤」と「鈴木」が出てくる。→「田中」と入力した場合、それが新しい値であることを示すアイコンを表示する。 というようなことをしようと思っているので。 >リンク切れのような不備が発生してもリカバリできなくなる可能性が大 ちょっと混乱したのですが、「可能性は小」の誤字ですよね? >発注に関して担当者を管理してまで明確な事が重要 これはなんとも言えないところですね……。Excel管理時代から担当者の列はありますし、備考に移動したりするのは考えづらいです。見直す余地はあると思いますが、できれば明確に管理したいところです。
sazi

2019/03/02 06:52 編集

>>リンク切れのような不備が発生してもリカバリできなくなる可能性が大 >ちょっと混乱したのですが、「可能性は小」の誤字ですよね? 管理されていない情報を復元しようとしても、重要な情報でなければ何が正しいのか不明な状況では復元できないという事です。※実際過去のデータは空欄なのではありませんか。 >できれば明確に管理したい 発注先の担当者が明確である事によって、どういったメリットがあるかです。 明確に管理するというなら、入力を必須にすべきですが、それは明確でないならその発注先は選択できないという事です。 一般的に発注に関しては価格などが重要で、それはその発注先で決まる事であって、先方の担当者によって変動するような事ではないでしょう? 極端に言うと、発注先がAmazonだったら、明確にするために担当者を問い合わせしますか? 仮にそれが得られたとして、それが重要な情報でしょうか? 考えられる事としては、問い合わせの際に担当者が分かれば問合せしやすい位だと思いますし、それならメモで十分です。
sazi

2019/03/02 06:42

データの関係から正規化を考える分には正しいと思いますが、そのデータが持つ意味も吟味しないと無用なものになってしまいます。
guest

0

こちらの方がイメージに近いのかな、と思い、書き直してみました。

投稿2019/03/02 06:13

ilove2dgirl

総合スコア50

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

7Kreuz

2019/03/02 07:13

Rel_01が違うのです 発注先(販売店)と商品は「多対多」の関係(ある販売店はさまざまな商品を売っている/ある商品はさまざまな販売店で売られている)なので、商品から発注先をたどることはできません
ilove2dgirl

2019/03/02 08:12 編集

えっと、すみません。恐らく、質問者様の捉えている意味での商品、はこのERDでは品物に該当します。言葉の定義が曖昧ですみません。このERD内での商品テーブルは、if_発注先_商品としても良いかもしれません。
guest

0

これで良いのではと思います。
発注先を指定したければ、担当者または商品の親テーブルをJOINすればいい、という作りです。
担当者が不明でない場合、商品と担当者の親の発注先IDが一致しなければ、はじく、という形で解決かと。

投稿2019/03/01 11:19

編集2019/03/01 11:23
ilove2dgirl

総合スコア50

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

7Kreuz

2019/03/02 05:55

「商品」が「発注先」を持つということでしょうか? 表の通り、「ペン」は「文具屋」でも「なんでも屋」でも買うことがあるので、それでは問題があるのです 誤読していたら申し訳ないです
ilove2dgirl

2019/03/02 06:00

同じペンでも、A社のペン、B社のペン、とあると思います。 M_商品のテーブルでは、どの会社のどの商品なのか、を商品idにより管理します。 ペン、という商品で集計を取る場合は、GROUP BY 商品名や、WHERE 商品名='ペン'などで絞れば、この作りで対応できると思います。
ilove2dgirl

2019/03/02 06:02 編集

何が問題なのか、イマイチ把握できなかったので、回答になっていなかったらすみません。
7Kreuz

2019/03/02 06:34

「発注先」というのは「メーカー」ではありません(メーカーの列は、商品テーブルには存在します)。 「東急ハンズで買ったパイロットのペン」と「Amazonで買ったパイロットのペン」は同じ商品として管理します。 もちろん、「東急ハンズで買ったパイロットのペン」と「東急ハンズで買ったゼブラのペン」は違う商品です。 例として上げた発注テーブルの、ID1とID6を見比べていただければ。
ilove2dgirl

2019/03/02 06:57

ご説明ありがとうございます。 そうしましたら、名称はともかく、構造としては、先ほど、別途回答させていただきましたので、そちらの設計をすると良いかと思います。 要件がわからないので、何とも言えませんが、最終形として、最初の質問欄にある発注テーブルのような形を出す必要があるのであれば、私の先ほどの回答の図にある、T_発注、M_商品、M_品物を親をたどっていく形でJOINしたVIEWまたはテーブルを表示用に別途作成すると良いと思います。 私が提示しているのは、あくまで、論理の設計のみなので、物理のレベルでは、これらをくっつけたりして、作成し、管理と表示は分ける、という形を取るのがスマートかなと思います。
guest

0

担当者テーブルをleft joinすればよいような

投稿2019/02/28 07:21

yambejp

総合スコア114839

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

7Kreuz

2019/02/28 07:33

「これらを結合すれば、冒頭の表を表現することができます。」の部分で、もちろんLEFT JOINを使っております。 問題は、存在しない「発注先/担当者」の組をチェックできないことなので……
guest

0

担当者テーブルの名前欄にNULLを許容して、すべての「発注先 - 担当者NULL」の組み合わせを登録、それから発注テーブルには担当者のみ登録して発注先を外す、という方策はどうでしょうか。

投稿2019/02/28 07:04

maisumakun

総合スコア145184

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

7Kreuz

2019/02/28 07:47

そうですね。 確かにあり得る方法だと思います。 ただ、そうすると、「商品:大根、発注先:八百屋、担当者:田中」のデータを挿入するときのフローは次のようになりますよね。 ①商品テーブルに「大根」を追加 ②発注先テーブルに「八百屋」を追加 ③担当者テーブルに「八百屋、NULL」を追加 ④担当者テーブルに「八百屋、田中」を追加 ⑤発注テーブルに追加 ……複雑になって大変だと思ったけど、整理してみると③が増えてるだけだからアリですね 検討してみます!
7Kreuz

2019/03/02 05:50

……と思いましたが、「発注」に対して本質的な「発注先」を外してしまうのは良くない気がしてきました saziさんご指摘の通り、「担当者」の重要度が一段下がるのは間違いないので
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問