データベースにおいて、他のテーブルの情報が変更された時にそのテーブルの情報も一緒に取得して、結合したい時があります。そんなときにテーブル同士の結合について
考えていきたいと思います。10月14日記事
目次
フィールドの中身の内容が変更されないような場合は特には考えなくていいですが、変更される恐れがある場合は外部結合や内部結合によって対応できるようにします。
ユーザが投稿した情報一覧が表示される仕組みにおいて、ユーザの名前(ニックネームやHN)が変更された場合にも、対応できるようにする。
例えば、アカウントテーブル(account)と記事テーブル(article)というものがあったとします。
account
account_id | accound_hn | account_email | account_passwordsalt |
1 | 田中太郎 | hoge@example.com | 0495ab094ef・・・・ |
2 | 山田花子 | huga@example.com | 0495ab094ef・・・・ |
3 | 鈴木次郎 | piyo@example.com | 0495ab094ef・・・・ |
テーブル作成のクエリ
CREATE TABLE account( account_id INT NOT NULL AUTO_INCREMENT, account_hn VARCHAR(255) NOT NULL, account_email VARCHAR(255) NOT NULL, account_passwordsalt VARCHAR(255) NOT NULL, PRIMARY KEY(account_id) );
そしてデータ登録
INSERT INTO account (account_hn,account_email,account_passwordsalt)VALUES('田中太郎','hoge@example.com','0495ab094ef・・・・'); INSERT INTO account (account_hn,account_email,account_passwordsalt)VALUES('山田花子','fuga@example.com','0495ab094ef・・・・'); INSERT INTO account (account_hn,account_email,account_passwordsalt)VALUES('鈴木次郎','piyo@example.com','0495ab094ef・・・・');
そして、記事テーブル作成
article
article_id | article_authorname | article_title | article_comment | status |
1 | 田中太郎 | タイトル1 | コメント1 | 1 |
2 | 田中太郎 | タイトル2 | コメント2 | 2 |
3 | 鈴木次郎 | タイトル3 | コメント3 | 1 |
※statusの1は公開状態を表す。2は削除状態を表す。
このような場合、 accountテーブルにて、ユーザの名前(ニックネームやHN)が変更された場合、articleテーブルのarticle_authornameの反映がめんどくさくなります。 このようなことを防ぐために、変わった場合にも反映できるような仕組みにしていくために外部結合や内部結合が使われます。
テーブル設計を変更していきます。 article
article_id | article_author_id | article_title | article_comment | status |
1 | 1 | タイトル1 | コメント1 | 1 |
2 | 1 | タイトル2 | コメント2 | 2 |
3 | 3 | タイトル3 | コメント3 | 1 |
のようにidで指定していきます。
よってarticle_テーブル作成のクエリは
CREATE TABLE article( article_id INT NOT NULL AUTO_INCREMENT, article_author_id INT NOT NULL, article_title VARCHAR(255) NOT NULL, article_comment text NOT NULL, article_status TINYINT NOT NULL, PRIMARY KEY(article_id) );
というように変更します。データ登録は
INSERT INTO article (article_author_id,article_title,article_comment,article_status) VALUES (1,'タイトル1','コメント1',1); INSERT INTO article (article_author_id,article_title,article_comment,article_status) VALUES (1,'タイトル2','コメント2',2); INSERT INTO article (article_author_id,article_title,article_comment,article_status) VALUES (3,'タイトル3','コメント3',1);
というように登録しておきます。
SELECT * FROM article LEFT JOIN account ON account.account_id = article.article_author_id;
また、記事が公開中の状態のみ取得したい場合は
SELECT * FROM article LEFT JOIN account ON account.account_id = article.article_author_id WHERE article_status = 1;
SELECT * FROM article JOIN account ON account.account_id = article.article_author_id;
また、記事が公開中の状態のみ取得したい場合は
SELECT * FROM article JOIN account ON account.account_id = article.article_author_id WHERE article_status = 1;
似たような感じですが、次のものを発行してみてください。
SELECT * FROM account LEFT JOIN article ON account.account_id = article.article_author_id; SELECT * FROM account JOIN article ON account.account_id = article.article_author_id;
山田花子さんがNULLとしてフィールドが作られている場合とそうでない場合に分けられると思います。
内部結合は「両方にレコード(フィールド)がないとレコードとして作成しない」
というもので、
外部結合は「片方に存在していなくてもレコード(フィールド)を作成する」
というものです。
UPDATE account SET account_hn = 'たなかたろー' WHERE account_id = 1;
これで、再び外部結合や内部結合のクエリを投げても反映されていることを確認できると思います。
基本は内部結合でいいですが、外部結合において、集計0件になる場合に必要になってきます。
以上