回答編集履歴

1

コメントへの回答を追記

2017/10/17 15:34

投稿

退会済みユーザー
test CHANGED
@@ -125,3 +125,65 @@
125
125
 
126
126
 
127
127
  どちらの場合も、プログラム側で動的にSQLを組み立てることになりますので、扱いやすい方を選ばれるとよいかと思います。
128
+
129
+
130
+
131
+ ---
132
+
133
+ 追記:
134
+
135
+
136
+
137
+ 今回のデータを考える場合、出発点となる非正規テーブルは下記のような形となるのかと思います。
138
+
139
+
140
+
141
+ * セットメニュー
142
+
143
+
144
+
145
+ |id|メニュー名|ドリンク1|個数|ドリンク2|個数|
146
+
147
+ |:--|:--:|--:|
148
+
149
+ |1|メニュー1|Water|1|POCARI SWEAT|1|
150
+
151
+ |2|メニュー2|Water|2|POCARI SWEAT|2|
152
+
153
+ |3|メニュー3|Water|1|POCARI SWEAT|1|
154
+
155
+
156
+
157
+ このテーブルをデータの重複や繰り返しをなくす形で分割した場合、質問に記載の3テーブルへの分割は、正規化後の構造として問題ないものと思われます。
158
+
159
+ 正規化の妥当性を検証するためには、分割後のテーブルから上記のテーブルが作成できることを確認されるとよいかと思います。
160
+
161
+ 前述しているSQLにドリンク名が表示されるように組み立てると、再現できるかと思います。
162
+
163
+
164
+
165
+ > 一番最後のSQLが理解できないです。なぜこのSQLで積集合みたいなことが出来るのですか?
166
+
167
+ > 仮にメニュ−2のwaterの個数が1だった場合、一つ目のwhereはメニュー123が該当してしまうため、結果としてメニュー123がピックアップされると思うのですが。。。。。
168
+
169
+
170
+
171
+ メニュー2のWaterの個数が1、POCARI SWEATの個数が2の場合を考えます。
172
+
173
+ この場合、下記のSQLの結果としてメニュー2も含まれるようになります。
174
+
175
+ > SELECT md.id FROM menudrink md WHERE m.id = md.menu_id AND drink_id = 1 AND md.number = 1
176
+
177
+
178
+
179
+ ただし、下記のSQLについては、POCARI SWEATの個数が2であるためにメニュー2のidは結果に含まれません。
180
+
181
+ > SELECT md.id FROM menudrink md WHERE m.id = md.menu_id AND drink_id = 2 AND md.number = 1
182
+
183
+
184
+
185
+ EXISTSは結果が1行でも存在すれば真(true)、0件であれば偽(false)となる演算で、上記2つのSELECT文をWHERE句のAND条件で使用しています。
186
+
187
+ AND条件ですので、どちらか一方が真となっても、もう一方が偽であればWHERE句の抽出条件としては成立しません。
188
+
189
+ ここではAND条件で積集合を求めていると考えていただいてもよいかと思います。