サーチ…
構文
INNER
とOUTER
は無視されます。FULL
はMySQLでは実装されていません。"commajoin"(
FROM a,b WHERE ax=by
whereFROM a,b WHERE ax=by
)は眉をひそめられています。代わりに、FROM a JOIN b ON ax=by
使用してください。FROM a JOIN B ON ax = by両方のテーブルで一致する行を含む。
LEFT JOINからb ax = = byは、
a
すべての行とb
一致するデータを含み、一致する行がない場合はNULLs
含みます。
結合例
DB上のテーブルを作成するためのクエリ
CREATE TABLE `user` (
`id` smallint(5) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(30) NOT NULL,
`course` smallint(5) unsigned DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB;
CREATE TABLE `course` (
`id` smallint(5) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(50) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB;
InnoDBテーブルを使用しており、user.courseとcourse.idが関連していることを知っているので、外部キー関係を指定できます。
ALTER TABLE `user`
ADD CONSTRAINT `FK_course`
FOREIGN KEY (`course`) REFERENCES `course` (`id`)
ON UPDATE CASCADE;
結合クエリ(内部結合)
SELECT user.name, course.name
FROM `user`
INNER JOIN `course` on user.course = course.id;
サブクエリを持つJOIN( "派生"テーブル)
SELECT x, ...
FROM ( SELECT y, ... FROM ... ) AS a
JOIN tbl ON tbl.x = a.y
WHERE ...
これは、サブクエリをテンポラリテーブルに評価し、次にそれをtbl
JOIN
します。
5.6以前では、一時表に索引を作成できませんでした。したがって、これは潜在的に非常に非効率的でした。
SELECT ...
FROM ( SELECT y, ... FROM ... ) AS a
JOIN ( SELECT x, ... FROM ... ) AS b ON b.x = a.y
WHERE ...
5.6では、オプティマイザが最適なインデックスを見つけ、即座に作成します。 (これにはオーバーヘッドがあるため、まだ完全ではありません。)
別の一般的なパラダイムは、何かを初期化するための副問い合わせを持つことです:
SELECT
@n := @n + 1,
...
FROM ( SELECT @n := 0 ) AS initialize
JOIN the_real_table
ORDER BY ...
(注:これは技術的にはON
ないことによって示されるCROSS JOIN
(デカルト積)ですが、副問合せはthe_real_table
n個の行に一致する必要がある行を1つだけ戻すので効率的the_real_table
。
オーダーのある顧客の検索 - テーマのバリエーション
これにより、すべての顧客のすべての注文が得られます。
SELECT c.CustomerName, o.OrderID
FROM Customers AS c
INNER JOIN Orders AS o
ON c.CustomerID = o.CustomerID
ORDER BY c.CustomerName, o.OrderID;
これにより、各顧客の注文数がカウントされます。
SELECT c.CustomerName, COUNT(*) AS 'Order Count'
FROM Customers AS c
INNER JOIN Orders AS o
ON c.CustomerID = o.CustomerID
GROUP BY c.CustomerID;
ORDER BY c.CustomerName;
また、数えますが、おそらくより高速です:
SELECT c.CustomerName,
( SELECT COUNT(*) FROM Orders WHERE CustomerID = c.CustomerID ) AS 'Order Count'
FROM Customers AS c
ORDER BY c.CustomerName;
オーダーのある顧客のみを一覧表示します。
SELECT c.CustomerName,
FROM Customers AS c
WHERE EXISTS ( SELECT * FROM Orders WHERE CustomerID = c.CustomerID )
ORDER BY c.CustomerName;
完全な外部結合
MySQLはFULL OUTER JOIN
サポートしていませんが、エミュレートする方法はあります。
データの設定
-- ----------------------------
-- Table structure for `owners`
-- ----------------------------
DROP TABLE IF EXISTS `owners`;
CREATE TABLE `owners` (
`owner_id` int(11) NOT NULL AUTO_INCREMENT,
`owner` varchar(30) DEFAULT NULL,
PRIMARY KEY (`owner_id`)
) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=latin1;
-- ----------------------------
-- Records of owners
-- ----------------------------
INSERT INTO `owners` VALUES ('1', 'Ben');
INSERT INTO `owners` VALUES ('2', 'Jim');
INSERT INTO `owners` VALUES ('3', 'Harry');
INSERT INTO `owners` VALUES ('6', 'John');
INSERT INTO `owners` VALUES ('9', 'Ellie');
-- ----------------------------
-- Table structure for `tools`
-- ----------------------------
DROP TABLE IF EXISTS `tools`;
CREATE TABLE `tools` (
`tool_id` int(11) NOT NULL AUTO_INCREMENT,
`tool` varchar(30) DEFAULT NULL,
`owner_id` int(11) DEFAULT NULL,
PRIMARY KEY (`tool_id`)
) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=latin1;
-- ----------------------------
-- Records of tools
-- ----------------------------
INSERT INTO `tools` VALUES ('1', 'Hammer', '9');
INSERT INTO `tools` VALUES ('2', 'Pliers', '1');
INSERT INTO `tools` VALUES ('3', 'Knife', '1');
INSERT INTO `tools` VALUES ('4', 'Chisel', '2');
INSERT INTO `tools` VALUES ('5', 'Hacksaw', '1');
INSERT INTO `tools` VALUES ('6', 'Level', null);
INSERT INTO `tools` VALUES ('7', 'Wrench', null);
INSERT INTO `tools` VALUES ('8', 'Tape Measure', '9');
INSERT INTO `tools` VALUES ('9', 'Screwdriver', null);
INSERT INTO `tools` VALUES ('10', 'Clamp', null);
何を見たいのですか?
私たちは誰がどのツールを所有しているのか、そしてどのツールが所有者を持たないのかを知るためのリストを得たいと考えています。
クエリ
これを達成するために、 UNION
を使用して2つのクエリを組み合わせることができます。この最初のクエリでは、 LEFT JOIN
を使用して所有者のツールに参加しています。これにより、すべての所有者が結果セットに追加されます。実際にツールを所有しているかどうかは関係ありません。
2番目のクエリでは、ツールを所有者に参加させるためにRIGHT JOIN
を使用しています。このようにして、結果セット内のすべてのツールを取得できNULL
。所有者が所有者でない場合、所有者列には単にNULL
が含まれNULL
。追加することによりWHERE
によってフィルタリングされ-clause owners.owner_id IS NULL
我々は唯一の右の結合テーブル内のデータを探しているとして、すでに、最初のクエリによって返されていないものをデータセットとして結果を定義しています。
UNION ALL
を使用しているので、2番目のクエリの結果セットは最初のクエリ結果セットにアタッチされます。
SELECT `owners`.`owner`, tools.tool
FROM `owners`
LEFT JOIN `tools` ON `owners`.`owner_id` = `tools`.`owner_id`
UNION ALL
SELECT `owners`.`owner`, tools.tool
FROM `owners`
RIGHT JOIN `tools` ON `owners`.`owner_id` = `tools`.`owner_id`
WHERE `owners`.`owner_id` IS NULL;
+-------+--------------+
| owner | tool |
+-------+--------------+
| Ben | Pliers |
| Ben | Knife |
| Ben | Hacksaw |
| Jim | Chisel |
| Harry | NULL |
| John | NULL |
| Ellie | Hammer |
| Ellie | Tape Measure |
| NULL | Level |
| NULL | Wrench |
| NULL | Screwdriver |
| NULL | Clamp |
+-------+--------------+
12 rows in set (0.00 sec)
3つのテーブルの内部結合
タグ付きのシンプルなウェブサイトに使用できる3つのテーブルがあるとしましょう。
- フィストテーブルはポスト用です。
- タグの2番目
- タグ&ポスト関係の3番目
拳のテーブル "ビデオゲーム"
id | タイトル | reg_date | コンテンツ |
---|---|---|---|
1 | バイオショック・インフィニット | 2016-08-08 | .... |
"タグ"テーブル
id | 名 |
---|---|
1 | 円 |
2 | エリザベス |
"tags_meta"テーブル
post_id | tag_id |
---|---|
1 | 2 |
SELECT videogame.id,
videogame.title,
videogame.reg_date,
tags.name,
tags_meta.post_id
FROM tags_meta
INNER JOIN videogame ON videogame.id = tags_meta.post_id
INNER JOIN tags ON tags.id = tags_meta.tag_id
WHERE tags.name = "elizabeth"
ORDER BY videogame.reg_date
このコードは、そのタグ "#elizabeth"に関連するすべての投稿を返すことができます
結合された結合
あなたが視覚指向の人であれば、このVennダイアグラムは、MySQL内に存在するさまざまな種類のJOIN
を理解するのに役立ちます。