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

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

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

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

PostgreSQL

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

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

SQLAlchemy

SQLAlchemyとはPython 用のORMライブラリです。MIT Licenceのオープンソースとして提供されています。

Q&A

解決済

2回答

1102閲覧

MySQL + SQLAlchemy、リレーションについて

sandalwalk

総合スコア77

MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

PostgreSQL

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

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

SQLAlchemy

SQLAlchemyとはPython 用のORMライブラリです。MIT Licenceのオープンソースとして提供されています。

0グッド

0クリップ

投稿2020/09/22 03:06

リレーショナルデータベースの考え方について質問です。
MySQL+SQLAlchemyを使ってレシピ管理のwebアプリを作っています。登録したいデータは、「メニュー名」、「材料」、「作り方」の3項目です。例えば、カレーであれば以下の様なデータを保存します。
メニュー名:カレー
材料:”じゃがいも”、”にんじん”、”玉ねぎ”、”カレールー”
作り方:”材料を切る”、”材料を煮る”、”カレールーを入れる”
PosgtreSQLであれば、array型が使えるので、
column1="カレー"
column2=[”じゃがいも”、”にんじん”、”玉ねぎ”、”カレールー”]
column3=[”材料を切る”、”材料を煮る”、”カレールーを入れる”]
とするだけで1つのテーブルでスッキリとデータを保存することができますが、MqSQLではarray型は使えないので、お手本のコードなどを参考にしながら以下のコードを書きましたが、

①MySQLでは本当にこんなに面倒な方法で上記のレシピを管理するのが正しいでしょうか。
②arrayが使えず、リレーショナルの考え方を頼りに、こんなに単純な事の為に3つもテーブルを作るメリットが理解できません。。。arrayがサポートされない理由をご存知でしたら教えて下さい。

python3

1''' 23''' 4class Recipe(db.Model): 5 __tablename__="recipe_table" 6 id = db.Column(db.Integer, primary_key=True) 7 name = db.Column(db.String(40)) 8 zairyou = db.relationship('Zairyou', backref='recipe') 9 tejun = db.relationship('Tejun', backref='recipe') 10 11class Zairyou(db.Model): 12 __tablename__="zairyou_table" 13 id = db.Column(db.Integer, primary_key=True) 14 zairyou_name = db.Column(db.String(20)) 15 recipe_id = db.Column(db.Integer, db.ForeignKey('recipe_table.id')) 16 17class Tejun(db.Model): 18 __tablename__="tejun_table" 19 id = db.Column(db.Integer, primary_key=True) 20 tejun_name = db.Column(db.String(20)) 21 recipe_id = db.Column(db.Integer, db.ForeignKey('recipe_table.id')) 22 23@app.route('/') 24def show_recipe(): 25 26 menu = Recipe.query.filter_by(name="カレー").first() 27 materials = menu.zairyou #backref=を使ってRecipeからSozaiへの 28relationを利用し、カレーの材料をzairyou_tableから取り出す 29 steps = menu.tejun #backref=を使ってRecipeからTejunへのrelationを利用し、カレーの作成手順をtejun_tableから取り出す 30 31if __name__ == '__main__': 32 app.run(debug = True)

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

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

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

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

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

guest

回答2

0

arrayがMYSQLに実装されていない理由ですが、
リレーショナルデータベースにとっては、オプションのようなもので
必ずしも実装されているものではないのかなと思います。

なかなかメリットが見えにくいかもしれません。
リレーショナルデータベースになるので、基本的には3つのテーブルに分けることが多いです。

分けることにより、データの検索が容易になります。
例えば、シチューというメニューを追加して、じゃがいもを使う場合です。

じゃがいもという食材を利用している、メニューを探すときにarrayの中に
配列で格納されていると、SQLで検索がしにくくありませんか?
別テーブルに分かれていると、検索がしやすくなります。

これが、リレーショナルデータベースの特徴なので逆にarray列自体が特殊なデータ型である
という認識の方が正しいです。

逆に検索や分析で利用しないのであれば、arrayでもよいと思います。
array型が無くても文字列型で、カンマ区切りで複数データを登録しても良いと思います。

なかなか、うまく説明できなかったので一度「正規化理論」を調べてみてください。

投稿2020/09/22 04:25

Kaiser

総合スコア295

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

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

sandalwalk

2020/09/22 07:23

とても分かりやすい説明でした。文字列型でカンマ区切りにするのは気づきませんでした。今後の為に記憶に留めておきます。今は学習中の身なので、リレーションを使う事にします。確かに、じゃがいもという食材から作れる料理名を検索する時は便利ですね。とりあえず、リレーショナルの使い方としては、こんな感じ(ソースコード)で正しいでしょうか? 本当にこんなに面倒な事するの?と思いながらネットで調べながら作っているので心配です。。。
Kaiser

2020/09/22 21:34

大きな問題は無いと思います。 コードをシンプルにしたければ、DB側でVIEWを利用しても良いかもしれません。
sandalwalk

2020/09/24 02:26

中間テーブルの考え方に導いて頂いたのでベストアンサーにさせて頂きました。
guest

0

ベストアンサー

①MySQLでは本当にこんなに面倒な方法で上記のレシピを管理するのが正しいでしょうか。

mysqlでもpostgresでも、多対多(レシピ:使う材料)みたいなテーブルでは配列として文字列保存するよりも中間テーブルを使うのが一般的かと

②arrayが使えず、

今回の用途なら数値でindexの振れるjson型が楽かもしれないですね
※indexが張れるではありません。キーがソートキー代わりに出来るという意味です(誤解を生まないように念のため補足)

arrayがサポートされない理由

mysqlの設計方針は知らないけど、適切な設計をすれば最悪でもenum、json、setで事足りるという考えかも

投稿2020/09/22 03:36

編集2020/09/22 03:47
hentaiman

総合スコア6426

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

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

sandalwalk

2020/09/22 07:13

①についてですが、「中間テーブル」の存在を初めて知った初心者ですので、にわか理解で書くのですが、具体的には、zairyou = db.relationship('Zairyou', backref='recipe') は書かず(使わず)、中間テーブルを介して料理名と材料がお互いを探す、ということでしょうか。
hentaiman

2020/09/22 07:31

そうです。 間接的にレシピのIDと素材のIDを紐づけた中間テーブルに情報を持つ事で素材データが冗長になる事を解消でき、また、じゃがいも料理を検索する時にはじゃがいものIDを持つレシピIDを中間テーブルから検索する事で速度もあがります。 「レシピ : 素材」に限らず、「曲 : ジャンル」、「書籍 : カテゴリー」みたいに多対多になるテーブルはまず中間テーブルが必要です。 「レシピ:料理手順」は一対多なので中間テーブルはいりません。 それと、回答には質問に書いてあるarrayの代替としてenum等をあげたけど、極力使わないで済むテーブル設計が良いです。
sandalwalk

2020/09/22 07:48

(1:多)の場合=> zairyou = db.relationship('Zairyou', backref='recipe')の書き方 (多:多)の場合=>中間テーブルを使う の理解で正しいでしょうか。 arrayの代替については、学習中の身にはお勧めしないという意見があるので、正統派の方法が知りたいと思い質問させて頂きましたので、今回は使わないつもりです。
hentaiman

2020/09/22 07:59

そうです。 学習中に限らずひとつの列に配列などの複数の値を内包するような設計はお勧めしません。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問