SQL文、検索の仕方について

解決済

回答 4

投稿

  • 評価
  • クリップ 1
  • VIEW 550

sueken5

score 10

 質問内容

皆さま、こんにちわ。私は今以下の様な条件で検索できるSQL分はないかと探しています。

table: estate

{
  id: 1,
  name: サンプル建設
},
{
  id: 2,
  name: サンプル不動産
}

table: tags
{
  id: 1,
  tag: 神奈川県,
  estate_id: 1
},
{
  id: 2,
  tag:ペット可,
  estate_id: 1
},
{
  id: 3,
  tag: 東京都,
  estate_id: 2
}

この様なテーブル構造で「神奈川県タグとペット可タグをもつ不動産」を検索できるSQL文はないでしょうか?皆様のお知恵をお借りできれば幸いです。

また、質問者自身RDBに詳しくないのでテーブル構造がそもそもまずいということもあると思います。ですのでもっと良いテーブル構造があればご教授いただければ幸いです。よろしくお願いします。

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 4

checkベストアンサー

+2

不動産屋さんには複数のタグが付くかもしれないし、同じタグが複数の不動産屋さんにつくかもしれませんよね?
そんな場合は中間テーブルを使って、多対多結合を表現するのがベストプラクティスです。

多対多結合ついて詳しくはググってください。

以下の3つのテーブルがあったとして

estatesテーブル
id(主キー)
name(ユニーク)

tagsテーブル
id (主キー)
name(ユニーク)

estates_tagsテーブル
tag_id(主キー)
estate_id(主キー)

SQLはこんな感じで

SELECT estates.name
FROM estates
INNER JOIN estates_tags
  ON estates_tags.estate_id = estates.id
INNER JOIN tags
  ON estates_tags.tag_id = tags.id
WHERE tags.name = "神奈川県" OR tags.name = "ペット可"
GROUP BY estates.name
HAVING COUNT(0) = 2


テーブルも追記します。

CREATE TABLE estates(id int PRIMARY KEY, name varchar(255) UNIQUE);

CREATE TABLE tags(id int PRIMARY KEY, name varchar(255) UNIQUE);

CREATE TABLE estates_tags(
  estate_id int NOT NULL,
  tag_id int NOT NULL,
  PRIMARY KEY(estate_id, tag_id),
  FOREIGN KEY(estate_id) REFERENCES estates(id),
  FOREIGN KEY(tag_id) REFERENCES tags(id));

INSERT INTO estates (id, name)
  VALUES (1, 'サンプル建設'), (2, 'サンプル不動産');

INSERT INTO tags (id, name)
  VALUES (1, '神奈川県'), (2, 'ペット可'), (3, '東京都');

INSERT INTO estates_tags(estate_id, tag_id)
VALUES (1, 1), (1, 2), (2, 3), (2, 2)

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/03/25 09:41

    非常にためになる回答ありがとうございます。今回ベストアンサーとさせていただきました。今後ともよろしくお願いします。

    キャンセル

+1

これでよかったような…。

SELECT e.name 
FROM estate AS e 
LEFT JOIN tags AS t 
  ON e.id = t.estate_id 
WHERE t.tag = '神奈川県' OR t.tag = 'ペット可' 
GROUP BY e.id 
ORDER BY e.id ASC;

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/03/24 11:44

    神奈川県タグとペット可タグをもつ ← これは、神奈川県タグまたはペット可タグをもつ
    かな?

    キャンセル

  • 2018/03/24 12:16 編集

    コメントありがとうございます。
    両方がいいです。その場合はORの部分をANDにしたらいいということでしょうか?

    キャンセル

  • 2018/03/24 12:33

    そうすると、結構変わってきちゃうと思います。時間があったらあとでレスします。

    キャンセル

+1

「神奈川県タグとペット可タグ」これは、「所在地」と「ペット可否」という独立した情報なので、「タグ」という一括りの構造にはしない方が良いです。

独立していればAND条件も容易になります。

当然登録する際の画面を考えると、単にタグの欄に列挙されるだけだと扱いづらいですし。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/03/25 09:40

    回答ありがとうございました。とてもためになりました。

    キャンセル

+1

一応、でけました。

お膳立て

create database test CHARACTER SET utf8mb4;

use test;

create table estate (
id int PRIMARY KEY,
name varchar(255)
) ENGINE InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;

create table tags(
id int PRIMARY KEY,
tag varchar(255),
estate_id int
) ENGINE InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;

INSERT INTO test.estate (id, name) VALUES (1, 'サンプル建設'), (2, 'サンプル不動産');
INSERT INTO test.tags (id, tag, estate_id) VALUES (1, '神奈川県', 1), (2, 'ペット可', 1), (3, '東京都', 2);

SELECTクエリー

SELECT e.id, e.name, t.ts
FROM estate AS e
LEFT JOIN (SELECT estate_id, group_concat(tag) AS ts FROM tags GROUP BY estate_id ORDER BY id ASC) AS t
ON e.id = t.estate_id
WHERE t.ts LIKE '%神奈川%' AND t.ts LIKE '%ペット可%';

SELCT結果

SELECT結果

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/03/25 09:39

    実際の例まで出してくれて本当にありがとうございます。しかし今回は多対多結合を利用するという一般的に採用されている例を提示してくれている方がいらっしゃったのでそちらの方をベストアンサーとさせていただきます。何卒ご了承ください。

    キャンセル

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

  • ただいまの回答率 90.22%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる