質問をすることでしか得られない、回答やアドバイスがある。

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

新規登録して質問してみよう
ただいま回答率
85.48%
MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

Q&A

解決済

2回答

1254閲覧

内部結合 WHERE

yuki911

総合スコア27

MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

0グッド

0クリップ

投稿2020/01/31 01:40

編集2020/01/31 02:13

現在phpとmysqlで掲示板を製作しています
title.phpでタイトルを書き込み、タイトルをリンクとして表示させ、リンクをクリックすると関連したtolk.phpに飛ぶ仕組みをにしています。
title.phpでboardsのidをtolk.phpに渡し、resテーブルにboards.idでINSERTしてます。
下記のSQL文でしたところ2つの処理は一緒の結果(タイトルの中でしたことは、他では表示されずそこでしか表示されない)になっているのですが、WHEREでも2つのテーブルを関連付けできているということですか?

また、このような処理?(関連した特定の場所でしか見えないこと)をなんと言いますか?

テーブル名:boards
id:int(11)
title:varchar(255)
uptime:datetime
テーブル名:res
id:int(11)
boards_id:int(11)
res_time:datetime
message:text

php

1$stmt = $pdo->prepare('SELECT * FROM res WHERE boards_id=?'); 2$params = []; 3 $params[] = $boards_id; 4 $stmt->execute($params);

php

1$stmt = $pdo->prepare('SELECT * FROM boards INNER JOIN res ON boards.id = res.id WHERE boards_id=?'); 2 $params = []; 3 $params[] = $boards_id; 4 $stmt->execute($params);

php

1<?php 2// title.php 3ini_set('display_errors', true); 4error_reporting(E_ALL); 5session_start(); 6 7require 'database.php'; 8$username = $_SESSION['username']; 9$error = []; 10 11date_default_timezone_set('Asia/Tokyo'); 12$title = filter_input(INPUT_POST, 'title'); 13$uptime = date("Y-m-d H:i:s"); 14if(filter_input(INPUT_SERVER,'REQUEST_METHOD') === 'POST'){ 15 16 if($title === ''){ 17 $error[] = 'タイトルは入力必須です。'; 18 }else if(strlen($title) > 10){ 19 $error[] = 'タイトルは10文字以内で入力してください。'; 20 } 21 22 if(count($error) === 0){ 23 try{ 24 $stmt = $pdo->prepare('INSERT INTO boards (id,title,uptime) VALUES (null,?,?)'); 25 $params = []; 26 $params[] = $title; 27 $params[] = $uptime; 28 $stmt->execute($params); 29 header('Location:title.php'); 30 exit; 31 }catch(PDOException $e){ 32 echo $e->getMessage(); 33 } 34 } 35} 36try{ 37 $stmt = $pdo->query('SELECT * FROM boards ORDER BY id DESC'); 38 $count = $stmt->rowCount(); 39 $rows = $stmt->fetchAll(); 40}catch(PDOException $e){ 41 echo $e->getMessage(); 42} 43?> 44 45<!DOCTYPE html> 46<html lang="ja"> 47 <head> 48 <!-- <link rel="stylesheet" href="/css/styles.css"> --> 49 <meta charset="utf-8"> 50 <title>メインページ</title> 51 <h1>掲示板へようこそ</h1> 52 </head> 53 <body> 54 <?php if(count($error) > 0) : ?> 55 <?php foreach($error as $e) : ?> 56 <p><?php echo h($e); ?></p> 57 <?php endforeach; ?> 58 <?php endif; ?> 59 <section> 60 <h2>新規投稿</h2> 61 <!-- 書き込み用フォーム --> 62 <form action="" method="post"> 63 <label for="title">タイトル</label><br> 64 <input type="text" name="title" id="title"><br> 65 <button type="submit">部屋を立てる</button> 66 </form> 67 </section> 68 <section> 69 <h2>投稿一覧</h2> 70 <p>現在の投稿は<span><?php echo $count; ?></span>件です</p> 71 <?php if(!empty($count)): ?> 72 <?php foreach($rows as $row): ?> 73 <div class="linkbox"> 74 <a href='tolk.php?boards_id=<?php echo $row['id']; ?>'> 75 <?php echo h($username); ?> 76 <?php echo h($row['uptime']); ?> <br> 77 <?php echo h($row['title']); ?> 78 <?php var_dump($row['id']); ?> 79 80 <a href="delete.php?delete_title_id=<?php echo $row['id'] ?>">削除</a> 81 <a href="change.php?change_title_id=<?php echo $row['id'] ?>">編集</a> 82 </a> 83 </div> 84 <?php endforeach; ?> 85 </ul> 86 <?php else: ?> 87 <p>投稿はまだありません。</p> 88 <?php endif; ?> 89 </section> 90 </body> 91</html> 92

php

1<?php 2// tolk.php 3ini_set('display_errors', true); 4error_reporting(E_ALL); 5session_start(); 6require 'database.php'; 7 8$username = $_SESSION['username']; 9$boards_id = filter_input(INPUT_GET, 'boards_id'); 10// $boards_id = $_GET['id']; 11$error = []; 12 13date_default_timezone_set('Asia/Tokyo'); 14$message = filter_input(INPUT_POST, 'message');//POST、入力された値を格納、未定義も防ぐ 15$res_time = date("Y-m-d H:i:s"); 16if(filter_input(INPUT_SERVER,'REQUEST_METHOD') === 'POST'){ 17 18 if($message === ''){ 19 $error[] = 'メッセージは入力必須です。'; 20 }else if(strlen($message) > 100){ 21 $error[] = 'メッセージは100文字以内で入力してください。'; 22 } 23 24 if(count($error) === 0){ 25 try{ 26 $stmt = $pdo->prepare('INSERT INTO res (id,boards_id,message,res_time) VALUES (null,?,?,?)'); 27 $params = []; 28 $params[] = $boards_id; 29 $params[] = $message; 30 $params[] = $res_time; 31 $stmt->execute($params); 32 header("Location:tolk.php?boards_id=$boards_id");//変数展開では、ダブルコーテーション 33 exit; 34 }catch(PDOException $e){ 35 echo $e->getMessage(); 36 } 37 } 38} 39try{ 40 $stmt = $pdo->prepare('SELECT * FROM res WHERE boards_id=?'); 41 $params = []; 42 $params[] = $boards_id; 43 $stmt->execute($params); 44 $count = $stmt->rowCount(); 45 $rows = $stmt->fetchAll(); 46}catch(PDOException $e){ 47 echo $e->getMessage(); 48} 49?> 50 51<!DOCTYPE html> 52<html lang="ja"> 53 <head> 54 <link rel="stylesheet" href="/css/styles.css"> 55 <meta charset="utf-8"> 56 <title>メインページ</title> 57 <h1>掲示板へようこそ</h1> 58 </head> 59 <body> 60 <?php if(count($error) > 0) : ?> 61 <?php foreach($error as $e) : ?> 62 <p><?php echo h($e); ?></p> 63 <?php endforeach; ?> 64 <?php endif; ?> 65 <section> 66 <h2>新規投稿</h2> 67 <form action="" method="post"> 68 <label for="message">メッセージ</label><br> 69 <input type="text" name="message" id="message"><br> 70 <button type="submit">投稿</button> 71 </form> 72 </section> 73 <section> 74 <h2>投稿一覧</h2> 75 <p>現在の投稿は<span><?php echo $count; ?></span></p> 76 <?php if(!empty($rows)): ?> 77 <?php foreach($rows as $row): ?> 78 <div class="linkbox"> 79 <?php echo h($username); ?> 80 <?php echo h($row['res_time']); ?><br> 81 <?php echo h($row['message']); ?> 82 <a href="delete.php?id=<?php echo $row['id'] ?>">削除</a> 83 <a href="change.php?id=<?php echo $row['id'] ?>">編集</a> 84 </div> 85 <?php var_dump($row['id']); ?> 86 <?php endforeach; ?> 87 </ul> 88 <?php else: ?> 89 <p>投稿はまだありません。</p> 90 <?php endif; ?> 91 </section> 92 </body> 93</html> 94

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Takumiboo

2020/01/31 01:56

本題と全く関係ないですが、会話などを意味する「トーク」であれば「talk」ですよ。
yambejp

2020/01/31 01:56

ちょっと何をききたいのか把握できません 「このような処理?(関連した特定の場所でしか見えないこと)をなんと言いますか? 」 SQL文だけ抽出して、そのどの部分に対する質問なのかをはっきり した方が良いと思います
guest

回答2

0

2つの処理は一緒の結果(タイトルの中でしたことは、他では表示されずそこでしか表示されない)になっているのですが、WHEREでも2つのテーブルを関連付けできているということですか?

Whereで関連付けされているのではなく、from 句で結合により関連付けられています。
Whereでは関連付けられた結果に対しての条件を指定しています。

また、このような処理?(関連した特定の場所でしか見えないこと)をなんと言いますか?

関連付けたものを取り出す項目はSelect句で指定します。
selectで指定していない項目は、selectの結果としては見えない事になります。

質問内容からは、見えないのではなく、単にその項目を取り出していないだけだと思います。

投稿2020/01/31 01:56

編集2020/01/31 02:07
sazi

総合スコア25173

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yuki911

2020/01/31 03:29 編集

回答ありがとうございます なるほどです。勘違いしていました FROM boards INNER JOIN resで結合により関連づけているのですね それぞれの項目のみ表示したい場合はそれぞれに関連付いている項目を取り出すということですね
guest

0

ベストアンサー

質問の趣旨とズレますけど、
resテーブルのidってなんのidですか?
resテーブル内のユニークなidを保持するためなのか、それともboard.idと紐付けるためのidなのか。

boards.id = res.id
って条件でJOINしてしまう前提で話をすすめると、
じゃぁテーブルres内で一つ一つの書き込みのユニーク性を
res_timeでみるのでしょうか、
全く同じタイミングで複数のboard宛に書き込みが生じた場合、
idとres_timeを組み合わせて削除できなくもないけど、
あまり良くない設計と言えます。

テーブル名:res
id:int(11)
boards_id:int(11) ←これを追加しましょう
res_time:datetime
message:text

INNER JOIN res ON boards.id = res.boards_id

などとして連結します。
こうすることで、res個別の削除はres.idを指定して簡単にできます。


FROM句とJOIN句で、テーブルの結合をON句に書かれた条件で行ったものに対して、
WHERE句の条件で絞り込みを行うものです。

例えば

SQL

1SELECT * FROM boards, res 2WHERE boards.id = res.boards_id AND boards.id = ? 3ORDER BY res.res_time;

のようにも書けなくもないですが、
テーブルboardsとテーブルresの全行を総当りで結合させたものの中から、
WHERE boards.id = res.boards_id AND boards.id = ?
の条件で絞り込みを行うため、得られる結果は一見同じに見えますが、
将来テーブルの行数が何千、何万、何十万同士を総当りで結合させる無駄な処理をした後に
絞り込みを行うと、総当たりの無駄な処理+膨大な量からの無駄な絞り込みということになり、
そういう無駄を省くためにも、
FROM句にJOIN句をつないでテーブルの結合を効率良く行うのがセオリーです。

投稿2020/01/31 01:59

編集2020/01/31 02:08
退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yuki911

2020/01/31 03:22

回答ありがとうございます boardsテーブルとresテーブルを紐づけるために、resテーブルにboards_id を追加しました。 また、紐づけるのは結合のためとはわかりますが、紐づけとはどういった意味なのでしょうか? boards.idとres.boards_idが一致したものに対して、boards_idの条件で絞り込みをかければいいのですね。 質問ですが、「テーブルres内で一つ一つの書き込みのユニーク性を」とありますが、掲示板にてユニーク性を考慮しなければいけない場合はありますか?
退会済みユーザー

退会済みユーザー

2020/01/31 03:45

紐づけとはどういった意味、については、 テーブルresだけに着目して、一つ一つのデータがなんのboards.idに絡むのかわかるようにするためです。 そのためにテーブルresではboards.idの値も保持して置かなければならないと言う。 (もしも、それ以外の方法、なんらかの計算やアルゴリズムを駆使してboards-resの特定が可能であれば、逆に知りたいです。) 基本的にテーブルboardsとresを連結して扱うものと思いますが、 boards.id一つに対して、res.idが複数存在する「一対多」の関係(=リレーション)にあたります。 データ構造をER図に起こしながら考えると良いでしょう。 掲示板にてユニーク性を考慮しなければいけない場合、について。 掲示板ですから、投稿を特定してテキストを更新する場合、あるいは削除する場合に、 どれが対象なのかを簡便に示すのに、最も簡単な方法は連番などかぶらない数値を一つ一つにつけることです。 そうすることでユニーク性をローコストに保てて、更新や削除を実装するときも簡便な方法でできます。 もっとも、投稿のみで更新や削除を絶対に実装しないということであれば、ユニーク性を担保する必要性も薄れます。
yuki911

2020/01/31 06:14

テーブルresだけに着目して、一つ一つのデータがなんのboards.idに絡むのかわかるようにするためです。 のところがわかりにくいので、もう少し詳しく説明お願いできませんか? 自分の考えでは、resテーブルにboards_idを追加することで、boards_idを両方持っている(紐付け)だと思っていました。 ER図、リレーションも勉強しておきます。 更新、削除も機能の一つとして考えているので、ユニーク性は担保しなければなりません また、プライマリーキーをidに指定していますが、プライマリーキーはユニーク性と言えますか?
退会済みユーザー

退会済みユーザー

2020/01/31 07:07

テーブルresに、テーブルboardsのidを示す意味で、わかりやすさも考慮してboards_idというカラムを持たせると書きましたが、 ただのカラムですし、単にintegerなどの型の数値データなだけです。 カラム名もわかりやすさを優先してboards_idとしましたが、bidでもfooでもbarでもなんでもいいわけです。 たまたまそのデータがテーブルboardsのidに同じ値を持つものがいる、というだけ。 たまたま1でした、1そのものには1である以外に意味がありませんが、 たまたまboards_idというカラム名でテーブルboardsのカラムidの値を保持する目的だとわかるようにしているだけです。 カラム名に、そのカラムが存在する理由付けや使い方に関連するような命名をしただけであり、 それだけではなんら紐付いてはいないこと(運用的に紐付けている)に注意です。 学習しているかどうかわかりませんが、その関係性をより明確にするために、 FOREIGN KEY(外部キー)という概念があります。 テーブルresのカラムboards_idに、FOREIGN KEY (boards.id)などと追加指定することで、 もうboards_idにはテーブルboardsのカラムidとして存在する値しか持てなくなります。 クエリーを工夫することで、やろうと思えば、boards上で削除されたidを持つres上のデータも一括で削除できたりします。
yuki911

2020/01/31 07:49

結合して初めて紐付くということなのですね 外部キーは聞いたことはありますが、深くは理解できていません 外部キーについても学習ようと思います
yuki911

2020/01/31 08:01

クエリーを工夫することで、やろうと思えば、boards上で削除されたidを持つres上のデータも一括で削除できたりします。 についてですが、boards上で削除されたidを持つres上のデータも一括で削除できたりします。は、外部キーの設定をしないとできないのですか?
yuki911

2020/01/31 08:22

クエリーを工夫することで、やろうと思えば、boards上で削除されたidを持つres上のデータも一括で削除できたりします。 とは、boards.idに外部キーを設定して、CASCADEを設定することですか?
退会済みユーザー

退会済みユーザー

2020/01/31 08:44 編集

FOREIGN KEYの指定を与えるのはあくまでres.boards_idに対してであり、 boards.idに与えるものではありません。 テーブルの主従関係の「従」側につけます。 https://dev.mysql.com/doc/refman/5.6/ja/create-table-foreign-keys.html ON DELETE CASCADE と ON UPDATE CASCADE の指定ができるようですね。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問