回答編集履歴

2

回答コメントを受けて、誤ったSQL修正&本物のデータ準拠で回答を追加

2018/07/09 04:06

投稿

nak
nak

スコア696

test CHANGED
@@ -72,8 +72,258 @@
72
72
 
73
73
  WHERE
74
74
 
75
- k.name IN (1, 3)
75
+ mk.id IN (1, 3)
76
76
 
77
77
  AND m.sex = 'woman'
78
78
 
79
79
  ```
80
+
81
+
82
+
83
+ ---
84
+
85
+
86
+
87
+ 質問へのコメントを受けて……。
88
+
89
+
90
+
91
+ すみません、回答が遅くなりました。
92
+
93
+ 上記2つめのSQLがエラーになった件については、こちらで提示したSQLが誤っていたので訂正させていただきました( `k.name IN ('いちご', 'バナナ')` ⇒ `mk.id IN (1, 3)` )。大変失礼いたしました。
94
+
95
+
96
+
97
+ もう一つのSQLでデータが取れなかった原因は調査しておりませんが、今回、実際のテーブルを提示していただいたので、そちらを元に改めて説明させていただきます。
98
+
99
+
100
+
101
+ 条件が「OR」でなく「AND」とのことですので、この場合は(データ量が多い場合、若干速度面で問題はありそうですが)EXISTSを使うと可読性の良いSQLができます。
102
+
103
+
104
+
105
+ ```sql
106
+
107
+ -- 事前準備SQL(テストデータに「ペット可、かつ、駅チカ物件」が存在しなかったので、テストデータを追加)
108
+
109
+ INSERT INTO property_data_osusume (
110
+
111
+ property_data_no_osusume,
112
+
113
+ property_data_data_no_osusume,
114
+
115
+ property_data_osusume_no
116
+
117
+ )
118
+
119
+ VALUES
120
+
121
+ ('10', '20', '9'),
122
+
123
+ ('11', '20', '23'),
124
+
125
+ ('12', '21', '9'),
126
+
127
+ ('13', '21', '23')
128
+
129
+ ;
130
+
131
+ ```
132
+
133
+
134
+
135
+ ```sql
136
+
137
+ -- 検索SQL
138
+
139
+ -- 条件:方位が西、または南西向きで、3DK、ペット可で駅チカ物件
140
+
141
+ -- ※元の条件では「3LDK」と書かれていましたが、テストデータに「3LDK」のデータが無かったので、3DKに変更しています。
142
+
143
+ SELECT
144
+
145
+ p.*
146
+
147
+ FROM
148
+
149
+ property_data AS p
150
+
151
+ WHERE
152
+
153
+ p.data_houi IN ('西', '南西')
154
+
155
+ AND
156
+
157
+ (p.data_madori1 = '3' AND p.data_madori2 = 'DK')
158
+
159
+ AND
160
+
161
+ EXISTS(
162
+
163
+ SELECT
164
+
165
+ *
166
+
167
+ FROM
168
+
169
+ property_data_osusume AS po
170
+
171
+ INNER JOIN
172
+
173
+ osusume AS o
174
+
175
+ ON
176
+
177
+ po.property_data_osusume_no = o.osusume_no
178
+
179
+ WHERE
180
+
181
+ p.data_no = po.property_data_data_no_osusume
182
+
183
+ AND
184
+
185
+ o.osusume_name = 'ペット可'
186
+
187
+ )
188
+
189
+ AND
190
+
191
+ EXISTS(
192
+
193
+ SELECT
194
+
195
+ *
196
+
197
+ FROM
198
+
199
+ property_data_osusume AS po
200
+
201
+ INNER JOIN
202
+
203
+ osusume AS o
204
+
205
+ ON
206
+
207
+ po.property_data_osusume_no = o.osusume_no
208
+
209
+ WHERE
210
+
211
+ p.data_no = po.property_data_data_no_osusume
212
+
213
+ AND
214
+
215
+ o.osusume_name = '駅チカ物件'
216
+
217
+ )
218
+
219
+ ```
220
+
221
+  
222
+
223
+  
224
+
225
+  
226
+
227
+ なお、多少可読性を犠牲にしてもいいから、とにかく速いSQLを!ということであれば、下記のような方法もあります。
228
+
229
+
230
+
231
+ ```sql
232
+
233
+ -- 検索SQL
234
+
235
+ -- 条件:方位が西、または南西向きで、3DK、ペット可で駅チカ物件
236
+
237
+ -- ※元の条件では「3LDK」と書かれていましたが、テストデータに「3LDK」のデータが無かったので、3DKに変更しています。
238
+
239
+ SELECT
240
+
241
+ p.*
242
+
243
+ FROM
244
+
245
+ property_data AS p
246
+
247
+ INNER JOIN
248
+
249
+ property_data_osusume AS po
250
+
251
+ ON
252
+
253
+ p.data_no = po.property_data_data_no_osusume
254
+
255
+ INNER JOIN
256
+
257
+ osusume AS o
258
+
259
+ ON
260
+
261
+ po.property_data_osusume_no = o.osusume_no
262
+
263
+ WHERE
264
+
265
+ p.data_houi IN ('西', '南西')
266
+
267
+ AND
268
+
269
+ (p.data_madori1 = '3' AND p.data_madori2 = 'DK')
270
+
271
+ AND
272
+
273
+ o.osusume_name IN ('ペット可', '駅チカ物件')
274
+
275
+ GROUP BY
276
+
277
+ p.data_no
278
+
279
+ HAVING
280
+
281
+ COUNT(*) = 2 -- o.osusume_nameのINの中に設定した値の数
282
+
283
+ ```
284
+
285
+
286
+
287
+ 解説:
288
+
289
+ INで「ペット可、または、駅チカ物件」としているので、いったんJOIN結果として
290
+
291
+
292
+
293
+ data_no osusume_name
294
+
295
+ ------- ------------
296
+
297
+ 21 ペット可
298
+
299
+ 21 駅チカ物件
300
+
301
+
302
+
303
+ が取得できる
304
+
305
+ ⇒data_noでGROUP BYする
306
+
307
+ ⇒data_no=21のcountは2となる
308
+
309
+ ⇒HAVING COUNT(*) = 2としているので、条件に合致するレコードとなり、取得できる
310
+
311
+
312
+
313
+ こちら、「ペット可」しか条件に合致しない物件の場合(仮にdata_no=99とする)、
314
+
315
+
316
+
317
+ data_no osusume_name
318
+
319
+ ------- ------------
320
+
321
+ 99 ペット可
322
+
323
+ が取得できる
324
+
325
+ ⇒data_noでGROUP BYする
326
+
327
+ ⇒data_no=99のcountは1となる
328
+
329
+ ⇒HAVING COUNT(*) = 2としているので、条件に合致しないレコードとなり、取得できない

1

おそらくlikeが予約語なので、テーブル名をmember_kudamonoに変更

2018/07/09 04:06

投稿

nak
nak

スコア696

test CHANGED
@@ -16,11 +16,11 @@
16
16
 
17
17
  INNER JOIN
18
18
 
19
- like AS l
19
+ member_kudamono AS mk
20
20
 
21
21
  ON
22
22
 
23
- m.no = l.member_no
23
+ m.no = mk.member_no
24
24
 
25
25
  INNER JOIN
26
26
 
@@ -28,7 +28,7 @@
28
28
 
29
29
  ON
30
30
 
31
- l.kudamono_no = k.no
31
+ mk.kudamono_no = k.no
32
32
 
33
33
  WHERE
34
34
 
@@ -41,6 +41,10 @@
41
41
 
42
42
 
43
43
  です。
44
+
45
+ ※質問文では「like」テーブルとなっていたところを「member_kudamono」テーブルに改名しています(SQLにおいて、おそらくlikeは予約語なので、使い勝手&可読性が悪くなるため)。
46
+
47
+ テーブル構造は「like」テーブルと同様です。
44
48
 
45
49
 
46
50
 
@@ -60,11 +64,11 @@
60
64
 
61
65
  INNER JOIN
62
66
 
63
- like AS l
67
+ member_kudamono AS mk
64
68
 
65
69
  ON
66
70
 
67
- m.no = l.member_no
71
+ m.no = mk.member_no
68
72
 
69
73
  WHERE
70
74