teratail header banner
teratail header banner
質問するログイン新規登録

回答編集履歴

8

修正

2019/03/02 23:43

投稿

sazi
sazi

スコア25430

answer CHANGED
@@ -61,7 +61,7 @@
61
61
 
62
62
  ---
63
63
  因みに配列の扱えるDBMSだと補集合とするような事をしなくても、非常に簡潔で高速な問合せが可能です。
64
- postgres でtablesにtags int[] でtagを配列で持つ場合、以下で同じ結果が得られます。
64
+ postgres でhotelsにtags int[] でtagを配列で持つ場合、以下で同じ結果が得られます。
65
65
  ```SQL
66
66
  select * from hotels where tags @> array[2,3]::int[]
67
67
  ```

7

推敲

2019/03/02 23:43

投稿

sazi
sazi

スコア25430

answer CHANGED
@@ -69,4 +69,4 @@
69
69
  ```SQL
70
70
  select hotel_id, unnest(tags) as tags_id from hotels
71
71
  ```
72
- DBMSの選定も重要な要素ですね
72
+ DBMSの選定も重要な要素だと思いませんか

6

追記

2019/03/02 14:24

投稿

sazi
sazi

スコア25430

answer CHANGED
@@ -57,4 +57,16 @@
57
57
  > なのでその他のタグが相当し、hotelが全件ヒットするかと思いました。
58
58
  > なぜ0件になるのでしょうか。
59
59
 
60
- こちらは質問①の補集合ですね。
60
+ こちらは質問①の補集合ですね。
61
+
62
+ ---
63
+ 因みに配列の扱えるDBMSだと補集合とするような事をしなくても、非常に簡潔で高速な問合せが可能です。
64
+ postgres でtablesにtags int[] でtagを配列で持つ場合、以下で同じ結果が得られます。
65
+ ```SQL
66
+ select * from hotels where tags @> array[2,3]::int[]
67
+ ```
68
+ hotels_tagsと同内容を得る場合は、unnestで配列を行に展開します。
69
+ ```SQL
70
+ select hotel_id, unnest(tags) as tags_id from hotels
71
+ ```
72
+ DBMSの選定も重要な要素ですね。

5

追記

2019/03/02 14:15

投稿

sazi
sazi

スコア25430

answer CHANGED
@@ -1,3 +1,5 @@
1
+ 解説
2
+ --
1
3
  SQLは集合を扱う言語です。このSQLは集合理論で言うところの補集合を利用したものです。
2
4
  NOTによって補集合を取得します。
3
5
 
@@ -26,4 +28,33 @@
26
28
  where tags_id=tags.tags_id and hotel_id=1
27
29
  )
28
30
  ```
29
- 上記で「複数のtagを全て含まないもの」が得られるので、それをNotにすることで補集合である「複数のtagを全て持つもの」となります。
31
+ 上記で「複数のtagを全て含まないもの」が得られるので、それをNotにすることで補集合である「複数のtagを全て持つもの」となります。
32
+
33
+ 追記(質問への回答)
34
+ --
35
+ ```SQL
36
+ select * from hotels
37
+ where exists(
38
+ select 1 from tags where tag in ('朝食付き','キャンセル無料')
39
+ )
40
+ ```
41
+ > 質問❶
42
+ > tagsテーブルにはhotelテーブルと紐付けできるものがないのでこれだと、
43
+ > inの中にtagsに存在するタグ名(WiFi無料、プール、朝食付きなど)を記入すればtrueとなり
44
+ > 全てを取得するということでしょうか。
45
+
46
+ hotelsとtagsに相関はありません。
47
+ 単に、tagに '朝食付き'または'キャンセル無料'というtagがあれば、hotelsは全件抽出されます。
48
+
49
+ ```SQL
50
+ select * from hotels
51
+ where not exists(
52
+ select 1 from tags where tag in ('朝食付き','キャンセル無料')
53
+ )
54
+ ```
55
+ > 質問❷
56
+ > こちらのSQLを実行すると結果は0件になります。in ('朝食付き','キャンセル無料'))でないもの。
57
+ > なのでその他のタグが相当し、hotelが全件ヒットするかと思いました。
58
+ > なぜ0件になるのでしょうか。
59
+
60
+ こちらは質問①の補集合ですね。

4

推敲

2019/03/02 04:57

投稿

sazi
sazi

スコア25430

answer CHANGED
@@ -16,8 +16,7 @@
16
16
 
17
17
  not existsにしているのに、'朝食付き','キャンセル無料'の何れかを含むものが含まれるのはおかしいと思うかもしれませんが、'朝食付き'のみは'キャンセル無料'を含んでいないので**True**で、'キャンセル無料'のみは'朝食付き'を含んでいないのでこれも**True**となります。
18
18
  '朝食付き'または'キャンセル無料'の何れも含むものは**False**となるのです。
19
-
20
- **ここが理解する為のポイントです。**
19
+ 「'朝食付き'と'キャンセル無料'」という**集合**をhotels_tagsが含まないものという事で、**ここが理解する為のポイントです。**
21
20
  その動作は、以下のSQLのhotel_idを変えてみると分かり易いでしょう。
22
21
  ```SQL
23
22
  select * from tags
@@ -27,5 +26,4 @@
27
26
  where tags_id=tags.tags_id and hotel_id=1
28
27
  )
29
28
  ```
30
-
31
29
  上記で「複数のtagを全て含まないもの」が得られるので、それをNotにすることで補集合である「複数のtagを全て持つもの」となります。

3

訂正

2019/03/02 02:58

投稿

sazi
sazi

スコア25430

answer CHANGED
@@ -10,6 +10,7 @@
10
10
  and not exists(
11
11
  select 1 from hotels_tags
12
12
  where tags_id=tags.tags_id
13
+ )
13
14
  ```
14
15
  上記では、全て含まないものと、'朝食付き','キャンセル無料'の何れかを含むものが含まれます。
15
16
 

2

推敲

2019/03/02 02:49

投稿

sazi
sazi

スコア25430

answer CHANGED
@@ -13,7 +13,7 @@
13
13
  ```
14
14
  上記では、全て含まないものと、'朝食付き','キャンセル無料'の何れかを含むものが含まれます。
15
15
 
16
- not existsにしているのに、'朝食付き','キャンセル無料'の何れかを含むものが含まれるのはおかしいと思うかもしれませんが、'朝食付き'のみは'キャンセル無料'を含んでいないので**True**で、'キャンセル無料'は'朝食付き'を含んでいないのでこれも**True**となります。
16
+ not existsにしているのに、'朝食付き','キャンセル無料'の何れかを含むものが含まれるのはおかしいと思うかもしれませんが、'朝食付き'のみは'キャンセル無料'を含んでいないので**True**で、'キャンセル無料'のみは'朝食付き'を含んでいないのでこれも**True**となります。
17
17
  '朝食付き'または'キャンセル無料'の何れも含むものは**False**となるのです。
18
18
 
19
19
  **ここが理解する為のポイントです。**

1

補足

2019/03/02 02:47

投稿

sazi
sazi

スコア25430

answer CHANGED
@@ -13,7 +13,8 @@
13
13
  ```
14
14
  上記では、全て含まないものと、'朝食付き','キャンセル無料'の何れかを含むものが含まれます。
15
15
 
16
- not existsにしているのに、'朝食付き','キャンセル無料'の何れかを含むものが含まれるのはおかしいと思うかもしれませんが、'朝食付き'のみは'キャンセル無料'を含んでいないので**True**で、'キャンセル無料'は'朝食付き'を含んでいないのでこれも**True**となります
16
+ not existsにしているのに、'朝食付き','キャンセル無料'の何れかを含むものが含まれるのはおかしいと思うかもしれませんが、'朝食付き'のみは'キャンセル無料'を含んでいないので**True**で、'キャンセル無料'は'朝食付き'を含んでいないのでこれも**True**となります
17
+ '朝食付き'または'キャンセル無料'の何れも含むものは**False**となるのです。
17
18
 
18
19
  **ここが理解する為のポイントです。**
19
20
  その動作は、以下のSQLのhotel_idを変えてみると分かり易いでしょう。