回答編集履歴

8

修正

2019/03/02 23:43

投稿

sazi
sazi

スコア25195

test CHANGED
@@ -124,7 +124,7 @@
124
124
 
125
125
  因みに配列の扱えるDBMSだと補集合とするような事をしなくても、非常に簡潔で高速な問合せが可能です。
126
126
 
127
- postgres でtablesにtags int[] でtagを配列で持つ場合、以下で同じ結果が得られます。
127
+ postgres でhotelsにtags int[] でtagを配列で持つ場合、以下で同じ結果が得られます。
128
128
 
129
129
  ```SQL
130
130
 

7

推敲

2019/03/02 23:43

投稿

sazi
sazi

スコア25195

test CHANGED
@@ -140,4 +140,4 @@
140
140
 
141
141
  ```
142
142
 
143
- DBMSの選定も重要な要素ですね
143
+ DBMSの選定も重要な要素だと思いませんか

6

追記

2019/03/02 14:24

投稿

sazi
sazi

スコア25195

test CHANGED
@@ -117,3 +117,27 @@
117
117
 
118
118
 
119
119
  こちらは質問①の補集合ですね。
120
+
121
+
122
+
123
+ ---
124
+
125
+ 因みに配列の扱えるDBMSだと補集合とするような事をしなくても、非常に簡潔で高速な問合せが可能です。
126
+
127
+ postgres でtablesにtags int[] でtagを配列で持つ場合、以下で同じ結果が得られます。
128
+
129
+ ```SQL
130
+
131
+ select * from hotels where tags @> array[2,3]::int[]
132
+
133
+ ```
134
+
135
+ hotels_tagsと同内容を得る場合は、unnestで配列を行に展開します。
136
+
137
+ ```SQL
138
+
139
+ select hotel_id, unnest(tags) as tags_id from hotels
140
+
141
+ ```
142
+
143
+ DBMSの選定も重要な要素ですね。

5

追記

2019/03/02 14:15

投稿

sazi
sazi

スコア25195

test CHANGED
@@ -1,3 +1,7 @@
1
+ 解説
2
+
3
+ --
4
+
1
5
  SQLは集合を扱う言語です。このSQLは集合理論で言うところの補集合を利用したものです。
2
6
 
3
7
  NOTによって補集合を取得します。
@@ -55,3 +59,61 @@
55
59
  ```
56
60
 
57
61
  上記で「複数のtagを全て含まないもの」が得られるので、それをNotにすることで補集合である「複数のtagを全て持つもの」となります。
62
+
63
+
64
+
65
+ 追記(質問への回答)
66
+
67
+ --
68
+
69
+ ```SQL
70
+
71
+ select * from hotels
72
+
73
+ where exists(
74
+
75
+ select 1 from tags where tag in ('朝食付き','キャンセル無料')
76
+
77
+ )
78
+
79
+ ```
80
+
81
+ > 質問❶
82
+
83
+ > tagsテーブルにはhotelテーブルと紐付けできるものがないのでこれだと、
84
+
85
+ > inの中にtagsに存在するタグ名(WiFi無料、プール、朝食付きなど)を記入すればtrueとなり
86
+
87
+ > 全てを取得するということでしょうか。
88
+
89
+
90
+
91
+ hotelsとtagsに相関はありません。
92
+
93
+ 単に、tagに '朝食付き'または'キャンセル無料'というtagがあれば、hotelsは全件抽出されます。
94
+
95
+
96
+
97
+ ```SQL
98
+
99
+ select * from hotels
100
+
101
+ where not exists(
102
+
103
+ select 1 from tags where tag in ('朝食付き','キャンセル無料')
104
+
105
+ )
106
+
107
+ ```
108
+
109
+ > 質問❷
110
+
111
+ > こちらのSQLを実行すると結果は0件になります。in ('朝食付き','キャンセル無料'))でないもの。
112
+
113
+ > なのでその他のタグが相当し、hotelが全件ヒットするかと思いました。
114
+
115
+ > なぜ0件になるのでしょうか。
116
+
117
+
118
+
119
+ こちらは質問①の補集合ですね。

4

推敲

2019/03/02 04:57

投稿

sazi
sazi

スコア25195

test CHANGED
@@ -34,9 +34,7 @@
34
34
 
35
35
  '朝食付き'または'キャンセル無料'の何れも含むものは**False**となるのです。
36
36
 
37
-
38
-
39
- **ここが理解する為のポイントです。**
37
+ 「'朝食付き'と'キャンセル無料'」という**集合**をhotels_tagsが含まないものという事で、**ここが理解する為のポイントです。**
40
38
 
41
39
  その動作は、以下のSQLのhotel_idを変えてみると分かり易いでしょう。
42
40
 
@@ -56,6 +54,4 @@
56
54
 
57
55
  ```
58
56
 
59
-
60
-
61
57
  上記で「複数のtagを全て含まないもの」が得られるので、それをNotにすることで補集合である「複数のtagを全て持つもの」となります。

3

訂正

2019/03/02 02:58

投稿

sazi
sazi

スコア25195

test CHANGED
@@ -21,6 +21,8 @@
21
21
  select 1 from hotels_tags
22
22
 
23
23
  where tags_id=tags.tags_id
24
+
25
+ )
24
26
 
25
27
  ```
26
28
 

2

推敲

2019/03/02 02:49

投稿

sazi
sazi

スコア25195

test CHANGED
@@ -28,7 +28,7 @@
28
28
 
29
29
 
30
30
 
31
- not existsにしているのに、'朝食付き','キャンセル無料'の何れかを含むものが含まれるのはおかしいと思うかもしれませんが、'朝食付き'のみは'キャンセル無料'を含んでいないので**True**で、'キャンセル無料'は'朝食付き'を含んでいないのでこれも**True**となります。
31
+ not existsにしているのに、'朝食付き','キャンセル無料'の何れかを含むものが含まれるのはおかしいと思うかもしれませんが、'朝食付き'のみは'キャンセル無料'を含んでいないので**True**で、'キャンセル無料'のみは'朝食付き'を含んでいないのでこれも**True**となります。
32
32
 
33
33
  '朝食付き'または'キャンセル無料'の何れも含むものは**False**となるのです。
34
34
 

1

補足

2019/03/02 02:47

投稿

sazi
sazi

スコア25195

test CHANGED
@@ -28,7 +28,9 @@
28
28
 
29
29
 
30
30
 
31
- not existsにしているのに、'朝食付き','キャンセル無料'の何れかを含むものが含まれるのはおかしいと思うかもしれませんが、'朝食付き'のみは'キャンセル無料'を含んでいないので**True**で、'キャンセル無料'は'朝食付き'を含んでいないのでこれも**True**となります
31
+ not existsにしているのに、'朝食付き','キャンセル無料'の何れかを含むものが含まれるのはおかしいと思うかもしれませんが、'朝食付き'のみは'キャンセル無料'を含んでいないので**True**で、'キャンセル無料'は'朝食付き'を含んでいないのでこれも**True**となります
32
+
33
+ '朝食付き'または'キャンセル無料'の何れも含むものは**False**となるのです。
32
34
 
33
35
 
34
36