ส่วนที่ 1 - เข้าร่วมและสหภาพ
คำตอบนี้ครอบคลุมถึง:
- ส่วนที่ 1
- ส่วนที่ 2
- คำถามย่อย - สิ่งที่พวกเขาสามารถใช้และสิ่งที่ควรระวัง
- คาร์ทีเซียนเข้าร่วม AKA - โอ้ความทุกข์ยาก!
มีหลายวิธีในการดึงข้อมูลจากหลายตารางในฐานข้อมูล ในคำตอบนี้ฉันจะใช้ไวยากรณ์การเข้าร่วม ANSI-92 สิ่งนี้อาจแตกต่างจากบทช่วยสอนอื่น ๆ ที่ใช้ไวยากรณ์ ANSI-89 ที่เก่ากว่า (และถ้าคุณคุ้นเคยกับ 89 อาจดูเหมือนใช้งานง่ายกว่า - แต่ทั้งหมดที่ฉันพูดได้คือลองทำ) เพราะง่ายกว่ามากเพื่อทำความเข้าใจเมื่อแบบสอบถามเริ่มซับซ้อนขึ้น ทำไมต้องใช้ มีประสิทธิภาพเพิ่มขึ้นหรือไม่? คำตอบสั้น ๆคือไม่ แต่มันเป็นเรื่องง่ายที่จะอ่านเมื่อคุณได้ใช้มัน ง่ายต่อการอ่านข้อความค้นหาที่เขียนโดยคนอื่นโดยใช้ไวยากรณ์นี้
ฉันจะใช้แนวคิดของนิวเคลียสเล็กซึ่งมีฐานข้อมูลเพื่อติดตามรถยนต์ที่มีอยู่ เจ้าของได้ว่าจ้างคุณเป็นคนคอมพิวเตอร์ไอทีของเขาและคาดหวังว่าคุณจะสามารถวางข้อมูลที่เขาขอไว้เมื่อหมวกหล่น
ฉันสร้างตารางการค้นหาจำนวนหนึ่งซึ่งจะใช้ในตารางสุดท้าย สิ่งนี้จะทำให้เรามีรูปแบบที่เหมาะสมในการทำงานจาก ในการเริ่มต้นฉันจะใช้คำสั่งของฉันกับฐานข้อมูลตัวอย่างที่มีโครงสร้างต่อไปนี้ ฉันจะพยายามคิดถึงข้อผิดพลาดทั่วไปที่เกิดขึ้นเมื่อเริ่มต้นและอธิบายสิ่งที่ผิดพลาดกับพวกเขา - รวมถึงการแสดงวิธีการแก้ไขให้ถูกต้อง
ตารางแรกเป็นเพียงรายการสีเพื่อให้เรารู้ว่าสีอะไรที่เรามีในลานรถ
mysql> create table colors(id int(3) not null auto_increment primary key,
-> color varchar(15), paint varchar(10));
Query OK, 0 rows affected (0.01 sec)
mysql> show columns from colors;
+-------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+----------------+
| id | int(3) | NO | PRI | NULL | auto_increment |
| color | varchar(15) | YES | | NULL | |
| paint | varchar(10) | YES | | NULL | |
+-------+-------------+------+-----+---------+----------------+
3 rows in set (0.01 sec)
mysql> insert into colors (color, paint) values ('Red', 'Metallic'),
-> ('Green', 'Gloss'), ('Blue', 'Metallic'),
-> ('White' 'Gloss'), ('Black' 'Gloss');
Query OK, 5 rows affected (0.00 sec)
Records: 5 Duplicates: 0 Warnings: 0
mysql> select * from colors;
+----+-------+----------+
| id | color | paint |
+----+-------+----------+
| 1 | Red | Metallic |
| 2 | Green | Gloss |
| 3 | Blue | Metallic |
| 4 | White | Gloss |
| 5 | Black | Gloss |
+----+-------+----------+
5 rows in set (0.00 sec)
ตารางยี่ห้อระบุยี่ห้อที่แตกต่างกันของรถยนต์ออก caryard อาจขายได้
mysql> create table brands (id int(3) not null auto_increment primary key,
-> brand varchar(15));
Query OK, 0 rows affected (0.01 sec)
mysql> show columns from brands;
+-------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+----------------+
| id | int(3) | NO | PRI | NULL | auto_increment |
| brand | varchar(15) | YES | | NULL | |
+-------+-------------+------+-----+---------+----------------+
2 rows in set (0.01 sec)
mysql> insert into brands (brand) values ('Ford'), ('Toyota'),
-> ('Nissan'), ('Smart'), ('BMW');
Query OK, 5 rows affected (0.00 sec)
Records: 5 Duplicates: 0 Warnings: 0
mysql> select * from brands;
+----+--------+
| id | brand |
+----+--------+
| 1 | Ford |
| 2 | Toyota |
| 3 | Nissan |
| 4 | Smart |
| 5 | BMW |
+----+--------+
5 rows in set (0.00 sec)
ตารางรุ่นจะครอบคลุมรถยนต์ประเภทต่างๆมันจะง่ายกว่าถ้าจะใช้รถยนต์ประเภทต่าง ๆ แทนที่จะเป็นรถรุ่นจริง
mysql> create table models (id int(3) not null auto_increment primary key,
-> model varchar(15));
Query OK, 0 rows affected (0.01 sec)
mysql> show columns from models;
+-------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+----------------+
| id | int(3) | NO | PRI | NULL | auto_increment |
| model | varchar(15) | YES | | NULL | |
+-------+-------------+------+-----+---------+----------------+
2 rows in set (0.00 sec)
mysql> insert into models (model) values ('Sports'), ('Sedan'), ('4WD'), ('Luxury');
Query OK, 4 rows affected (0.00 sec)
Records: 4 Duplicates: 0 Warnings: 0
mysql> select * from models;
+----+--------+
| id | model |
+----+--------+
| 1 | Sports |
| 2 | Sedan |
| 3 | 4WD |
| 4 | Luxury |
+----+--------+
4 rows in set (0.00 sec)
และสุดท้ายเพื่อผูกตารางอื่น ๆ ทั้งหมดนี้ตารางที่ผูกทุกอย่างเข้าด้วยกัน จริง ๆ แล้วฟิลด์ ID เป็นหมายเลขลอตที่ไม่ซ้ำกันซึ่งใช้ระบุรถยนต์
mysql> create table cars (id int(3) not null auto_increment primary key,
-> color int(3), brand int(3), model int(3));
Query OK, 0 rows affected (0.01 sec)
mysql> show columns from cars;
+-------+--------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+--------+------+-----+---------+----------------+
| id | int(3) | NO | PRI | NULL | auto_increment |
| color | int(3) | YES | | NULL | |
| brand | int(3) | YES | | NULL | |
| model | int(3) | YES | | NULL | |
+-------+--------+------+-----+---------+----------------+
4 rows in set (0.00 sec)
mysql> insert into cars (color, brand, model) values (1,2,1), (3,1,2), (5,3,1),
-> (4,4,2), (2,2,3), (3,5,4), (4,1,3), (2,2,1), (5,2,3), (4,5,1);
Query OK, 10 rows affected (0.00 sec)
Records: 10 Duplicates: 0 Warnings: 0
mysql> select * from cars;
+----+-------+-------+-------+
| id | color | brand | model |
+----+-------+-------+-------+
| 1 | 1 | 2 | 1 |
| 2 | 3 | 1 | 2 |
| 3 | 5 | 3 | 1 |
| 4 | 4 | 4 | 2 |
| 5 | 2 | 2 | 3 |
| 6 | 3 | 5 | 4 |
| 7 | 4 | 1 | 3 |
| 8 | 2 | 2 | 1 |
| 9 | 5 | 2 | 3 |
| 10 | 4 | 5 | 1 |
+----+-------+-------+-------+
10 rows in set (0.00 sec)
นี่จะทำให้เรามีข้อมูลมากพอ (ฉันหวังว่า) เพื่อปกปิดตัวอย่างด้านล่างของการเข้าร่วมประเภทต่าง ๆ และยังให้ข้อมูลที่เพียงพอเพื่อทำให้พวกเขาคุ้มค่า
ดังนั้นการเข้าสู่กรวดของมันเจ้านายต้องการที่จะรู้รหัสของทุกรถสปอร์ตที่เขามี
นี่คือการรวมสองตารางที่เรียบง่าย เรามีตารางที่ระบุรูปแบบและตารางพร้อมสต็อกที่มีอยู่ในนั้น อย่างที่คุณเห็นข้อมูลในmodel
คอลัมน์ของcars
ตารางเกี่ยวข้องกับmodels
คอลัมน์ของcars
ตารางที่เรามี ตอนนี้เรารู้แล้วว่าตาราง model มี ID 1
สำหรับSports
ดังนั้นให้เขียนการเข้าร่วม
select
ID,
model
from
cars
join models
on model=ID
ดังนั้นแบบสอบถามนี้ดูดีใช่ไหม เราได้ระบุสองตารางและมีข้อมูลที่เราต้องการและใช้การเข้าร่วมที่ระบุคอลัมน์ที่จะเข้าร่วมอย่างถูกต้อง
ERROR 1052 (23000): Column 'ID' in field list is ambiguous
โอ้โห! ข้อผิดพลาดในข้อความค้นหาแรกของเรา! ใช่และมันก็เป็นลูกพลัม คุณเห็นแล้วว่าคิวรี่นั้นมีคอลัมน์ที่ถูกต้อง แต่มีบางคอลัมน์อยู่ในทั้งสองตารางดังนั้นฐานข้อมูลจะสับสนว่าคอลัมน์จริงที่เราหมายถึงและที่ใด มีสองวิธีแก้ไขปัญหานี้ อันแรกนั้นดีและเรียบง่ายเราสามารถใช้tableName.columnName
บอกฐานข้อมูลว่าเราหมายถึงอะไรแบบนี้
select
cars.ID,
models.model
from
cars
join models
on cars.model=models.ID
+----+--------+
| ID | model |
+----+--------+
| 1 | Sports |
| 3 | Sports |
| 8 | Sports |
| 10 | Sports |
| 2 | Sedan |
| 4 | Sedan |
| 5 | 4WD |
| 7 | 4WD |
| 9 | 4WD |
| 6 | Luxury |
+----+--------+
10 rows in set (0.00 sec)
อีกอันอาจใช้บ่อยกว่าและเรียกว่านามแฝงตาราง ตารางในตัวอย่างนี้มีชื่อที่ง่ายและสั้น แต่พิมพ์สิ่งที่KPI_DAILY_SALES_BY_DEPARTMENT
อาจจะเก่าไปอย่างรวดเร็วดังนั้นวิธีง่ายๆคือตั้งชื่อตารางตามนี้:
select
a.ID,
b.model
from
cars a
join models b
on a.model=b.ID
ตอนนี้กลับไปที่คำขอ อย่างที่คุณเห็นว่าเรามีข้อมูลที่เราต้องการ แต่เราก็มีข้อมูลที่ไม่ได้ถามด้วยดังนั้นเราจึงจำเป็นต้องรวมส่วนคำสั่งในการรับรถสปอร์ตตามที่ถูกถามเท่านั้น ตามที่ฉันต้องการวิธีการนามแฝงของตารางแทนที่จะใช้ชื่อตารางซ้ำแล้วซ้ำอีกฉันจะยึดมันจากจุดนี้เป็นต้นไป
เห็นได้ชัดว่าเราต้องเพิ่มส่วนคำสั่งลงในแบบสอบถามของเรา เราสามารถระบุรถยนต์กีฬาทั้งโดยหรือID=1
model='Sports'
ในขณะที่ ID ถูกทำดัชนีและคีย์หลัก (และเกิดขึ้นกับการพิมพ์น้อยลง) ให้ใช้ในการสืบค้นของเรา
select
a.ID,
b.model
from
cars a
join models b
on a.model=b.ID
where
b.ID=1
+----+--------+
| ID | model |
+----+--------+
| 1 | Sports |
| 3 | Sports |
| 8 | Sports |
| 10 | Sports |
+----+--------+
4 rows in set (0.00 sec)
บิงโก! เจ้านายมีความสุข แน่นอนเป็นเจ้านายและไม่เคยมีความสุขกับสิ่งที่เขาถามหาเขาดูที่ข้อมูลแล้วพูดว่าฉันต้องการสีได้เป็นอย่างดี
ตกลงดังนั้นเรามีส่วนที่ดีของแบบสอบถามของเราที่เขียนไปแล้ว แต่เราจำเป็นต้องใช้ตารางที่สามซึ่งเป็นสี ตอนนี้ตารางข้อมูลหลักของเราจัดcars
เก็บรหัสสีรถยนต์และลิงค์นี้กลับไปที่คอลัมน์รหัสสี ดังนั้นในลักษณะที่คล้ายคลึงกับต้นฉบับเราสามารถเข้าร่วมตารางที่สาม:
select
a.ID,
b.model
from
cars a
join models b
on a.model=b.ID
join colors c
on a.color=c.ID
where
b.ID=1
+----+--------+
| ID | model |
+----+--------+
| 1 | Sports |
| 3 | Sports |
| 8 | Sports |
| 10 | Sports |
+----+--------+
4 rows in set (0.00 sec)
ประณามแม้ว่าตารางจะถูกรวมอย่างถูกต้องและมีการเชื่อมโยงคอลัมน์ที่เกี่ยวข้องเราลืมที่จะดึงข้อมูลจริงจากตารางใหม่ที่เราเพิ่งเชื่อมโยง
select
a.ID,
b.model,
c.color
from
cars a
join models b
on a.model=b.ID
join colors c
on a.color=c.ID
where
b.ID=1
+----+--------+-------+
| ID | model | color |
+----+--------+-------+
| 1 | Sports | Red |
| 8 | Sports | Green |
| 10 | Sports | White |
| 3 | Sports | Black |
+----+--------+-------+
4 rows in set (0.00 sec)
ใช่แล้วนั่นคือหัวหน้าของเรา ทีนี้มาอธิบายเรื่องนี้ให้ละเอียดหน่อย ตามที่คุณเห็นส่วนfrom
คำสั่งในคำสั่งของเราเชื่อมโยงตารางหลักของเรา (ฉันมักจะใช้ตารางที่มีข้อมูลมากกว่าตารางการค้นหาหรือส่วนข้อมูล) การสืบค้นจะทำงานได้ดีเช่นเดียวกับตารางที่สลับไปมาทั้งหมด เรากลับมาที่ข้อความค้นหานี้เพื่ออ่านในเวลาไม่กี่เดือนดังนั้นจึงเป็นการดีที่สุดที่จะลองเขียนคำถามที่จะดีและง่ายต่อการเข้าใจ - จัดวางไว้อย่างสังหรณ์ใจใช้การเยื้องที่ดีเพื่อให้ทุกอย่างชัดเจน มันอาจเป็นไปได้ถ้าคุณยังสอนผู้อื่นให้ลองปลูกฝังคุณลักษณะเหล่านี้ในแบบสอบถามของพวกเขา - โดยเฉพาะถ้าคุณจะแก้ไขปัญหาเหล่านั้น
เป็นไปได้ทั้งหมดที่จะเชื่อมโยงตารางมากขึ้นเรื่อย ๆ ในลักษณะนี้
select
a.ID,
b.model,
c.color
from
cars a
join models b
on a.model=b.ID
join colors c
on a.color=c.ID
join brands d
on a.brand=d.ID
where
b.ID=1
แม้ว่าฉันลืมที่จะรวมตารางที่เราอาจต้องการเข้าร่วมมากกว่าหนึ่งคอลัมน์ในjoin
คำชี้แจงนี่คือตัวอย่าง หากmodels
ตารางมีโมเดลเฉพาะแบรนด์และดังนั้นจึงมีคอลัมน์brand
ที่เชื่อมโยงกลับไปที่brands
ตารางในID
ฟิลด์ก็สามารถทำได้ดังนี้:
select
a.ID,
b.model,
c.color
from
cars a
join models b
on a.model=b.ID
join colors c
on a.color=c.ID
join brands d
on a.brand=d.ID
and b.brand=d.ID
where
b.ID=1
คุณสามารถดูแบบสอบถามด้านบนไม่เพียง แต่เชื่อมโยงตารางที่รวมเข้ากับตารางหลักcars
แต่ยังระบุการรวมระหว่างตารางที่เข้าร่วมแล้ว หากสิ่งนี้ยังไม่เสร็จสิ้นผลลัพธ์จะถูกเรียกว่าการเข้าร่วมคาร์ทีเซียนซึ่งเป็น dba ที่พูดไม่ดี การรวมคาร์ทีเซียนคือการที่แถวถูกส่งคืนเนื่องจากข้อมูลไม่ได้บอกฐานข้อมูลถึงวิธี จำกัด ผลลัพธ์ดังนั้นแบบสอบถามจะส่งคืนแถวทั้งหมดที่ตรงกับเกณฑ์
ดังนั้นเพื่อให้ตัวอย่างของการเข้าร่วมคาร์ทีเซียนให้เรียกใช้แบบสอบถามต่อไปนี้:
select
a.ID,
b.model
from
cars a
join models b
+----+--------+
| ID | model |
+----+--------+
| 1 | Sports |
| 1 | Sedan |
| 1 | 4WD |
| 1 | Luxury |
| 2 | Sports |
| 2 | Sedan |
| 2 | 4WD |
| 2 | Luxury |
| 3 | Sports |
| 3 | Sedan |
| 3 | 4WD |
| 3 | Luxury |
| 4 | Sports |
| 4 | Sedan |
| 4 | 4WD |
| 4 | Luxury |
| 5 | Sports |
| 5 | Sedan |
| 5 | 4WD |
| 5 | Luxury |
| 6 | Sports |
| 6 | Sedan |
| 6 | 4WD |
| 6 | Luxury |
| 7 | Sports |
| 7 | Sedan |
| 7 | 4WD |
| 7 | Luxury |
| 8 | Sports |
| 8 | Sedan |
| 8 | 4WD |
| 8 | Luxury |
| 9 | Sports |
| 9 | Sedan |
| 9 | 4WD |
| 9 | Luxury |
| 10 | Sports |
| 10 | Sedan |
| 10 | 4WD |
| 10 | Luxury |
+----+--------+
40 rows in set (0.00 sec)
พระเจ้าที่ดีน่าเกลียด แต่เท่าที่เป็นฐานข้อมูลเป็นห่วงก็คือว่าสิ่งที่ถูกถามหา ในแบบสอบถามที่เราถามหาID
จากcars
และจากmodel
models
อย่างไรก็ตามเนื่องจากเราไม่ได้ระบุวิธีเข้าร่วมตารางฐานข้อมูลจึงจับคู่ทุกแถวจากตารางแรกกับทุกแถวจากตารางที่สอง
โอเคเจ้านายกลับมาแล้วและเขาต้องการข้อมูลเพิ่มเติมอีกครั้ง ฉันต้องการรายการเดียวกัน แต่ยังรวมถึง 4WD อยู่ด้วย
อย่างไรก็ตามสิ่งนี้ทำให้เรามีข้อแก้ตัวที่ดีในการดูสองวิธีที่แตกต่างกันเพื่อบรรลุเป้าหมายนี้ เราสามารถเพิ่มเงื่อนไขอื่นในส่วนคำสั่งเช่นนี้:
select
a.ID,
b.model,
c.color
from
cars a
join models b
on a.model=b.ID
join colors c
on a.color=c.ID
join brands d
on a.brand=d.ID
where
b.ID=1
or b.ID=3
ในขณะที่ข้างต้นจะทำงานได้ดีอย่างสมบูรณ์ให้ดูที่มันแตกต่างกันนี้เป็นข้อแก้ตัวที่ดีในการแสดงวิธีการunion
ทำงานของแบบสอบถาม
เรารู้ว่าสิ่งต่อไปนี้จะคืนรถสปอร์ตทุกคัน:
select
a.ID,
b.model,
c.color
from
cars a
join models b
on a.model=b.ID
join colors c
on a.color=c.ID
join brands d
on a.brand=d.ID
where
b.ID=1
และต่อไปนี้จะส่งคืน 4WD ทั้งหมด:
select
a.ID,
b.model,
c.color
from
cars a
join models b
on a.model=b.ID
join colors c
on a.color=c.ID
join brands d
on a.brand=d.ID
where
b.ID=3
ดังนั้นโดยการเพิ่มunion all
ประโยคระหว่างพวกเขาผลลัพธ์ของแบบสอบถามที่สองจะถูกผนวกเข้ากับผลลัพธ์ของแบบสอบถามแรก
select
a.ID,
b.model,
c.color
from
cars a
join models b
on a.model=b.ID
join colors c
on a.color=c.ID
join brands d
on a.brand=d.ID
where
b.ID=1
union all
select
a.ID,
b.model,
c.color
from
cars a
join models b
on a.model=b.ID
join colors c
on a.color=c.ID
join brands d
on a.brand=d.ID
where
b.ID=3
+----+--------+-------+
| ID | model | color |
+----+--------+-------+
| 1 | Sports | Red |
| 8 | Sports | Green |
| 10 | Sports | White |
| 3 | Sports | Black |
| 5 | 4WD | Green |
| 7 | 4WD | White |
| 9 | 4WD | Black |
+----+--------+-------+
7 rows in set (0.00 sec)
อย่างที่คุณเห็นผลลัพธ์ของแบบสอบถามแรกจะถูกส่งกลับก่อนตามด้วยผลลัพธ์ของแบบสอบถามที่สอง
ในตัวอย่างนี้แน่นอนว่าจะง่ายกว่ามากในการใช้การสืบค้นแรก แต่การunion
สืบค้นสามารถทำได้ดีสำหรับกรณีเฉพาะ พวกเขาเป็นวิธีที่ยอดเยี่ยมในการส่งคืนผลลัพธ์ที่เฉพาะเจาะจงจากตารางจากตารางที่ไม่ได้รวมเข้าด้วยกันได้ง่ายหรือสำหรับตารางที่ไม่เกี่ยวข้องอย่างสมบูรณ์ มีกฎบางอย่างที่ต้องปฏิบัติตามอย่างไรก็ตาม
- ประเภทคอลัมน์จากแบบสอบถามแรกจะต้องตรงกับประเภทคอลัมน์จากแบบสอบถามอื่น ๆ ด้านล่าง
- ชื่อของคอลัมน์จากแบบสอบถามแรกจะถูกใช้เพื่อระบุชุดผลลัพธ์ทั้งหมด
- จำนวนคอลัมน์ในแต่ละแบบสอบถามจะต้องเหมือนกัน
ตอนนี้คุณอาจสงสัยว่าความแตกต่างระหว่างการใช้งานunion
กับunion all
อะไร union
แบบสอบถามจะลบที่ซ้ำกันในขณะที่union all
จะไม่ นี่หมายความว่ามีการใช้งานเล็กน้อยเมื่อใช้union
เกินunion all
แต่ผลลัพธ์อาจมีค่า - ฉันจะไม่คาดเดากับสิ่งนั้นในเรื่องนี้
ในบันทึกนี้มันอาจจะคุ้มค่าที่จะต้องสังเกตโน้ตเพิ่มเติมที่นี่
- หากเราต้องการเรียงลำดับผลลัพธ์เราสามารถใช้
order by
แต่คุณไม่สามารถใช้ชื่อแทนได้อีก ในแบบสอบถามด้านบนการผนวกorder by a.ID
จะส่งผลให้เกิดข้อผิดพลาด - เท่าที่ผลลัพธ์เกี่ยวข้องคอลัมน์จะถูกเรียกID
มากกว่าa.ID
- แม้ว่าจะใช้นามแฝงเดียวกันในแบบสอบถามทั้งสอง
- เราสามารถมีได้เพียงหนึ่ง
order by
คำสั่งและมันจะต้องเป็นคำสั่งสุดท้าย
สำหรับตัวอย่างถัดไปฉันกำลังเพิ่มแถวพิเศษสองสามแถวในตารางของเรา
ฉันเพิ่มลงHolden
ในตารางแบรนด์แล้ว ฉันได้เพิ่มแถวcars
ที่มีcolor
ค่า12
ซึ่งไม่มีการอ้างอิงในตารางสี
โอเคเจ้านายกลับมาอีกครั้งเห่าร้องขอ - * ฉันต้องการนับแต่ละยี่ห้อที่เราบรรทุกและจำนวนรถยนต์ในนั้น! '- โดยทั่วไปเราเพิ่งไปยังส่วนที่น่าสนใจของการสนทนาของเราและหัวหน้าต้องการทำงานมากขึ้น .
Rightyo สิ่งแรกที่เราต้องทำคือรับรายชื่อแบรนด์ที่เป็นไปได้ทั้งหมด
select
a.brand
from
brands a
+--------+
| brand |
+--------+
| Ford |
| Toyota |
| Nissan |
| Smart |
| BMW |
| Holden |
+--------+
6 rows in set (0.00 sec)
ตอนนี้เมื่อเราเข้าร่วมในตารางรถยนต์ของเราเราได้รับผลดังต่อไปนี้:
select
a.brand
from
brands a
join cars b
on a.ID=b.brand
group by
a.brand
+--------+
| brand |
+--------+
| BMW |
| Ford |
| Nissan |
| Smart |
| Toyota |
+--------+
5 rows in set (0.00 sec)
แน่นอนว่าเป็นปัญหา - เราไม่เห็นการกล่าวถึงHolden
แบรนด์ที่น่ารักที่ฉันเพิ่มเข้าไป
นี่เป็นเพราะการเข้าร่วมค้นหาการจับคู่แถวในตารางทั้งสอง เนื่องจากไม่มีข้อมูลในรถยนต์ที่เป็นประเภทHolden
จึงไม่ส่งคืน นี่คือที่เราสามารถใช้outer
เข้าร่วม สิ่งนี้จะส่งคืนผลลัพธ์ทั้งหมดจากตารางหนึ่งไม่ว่าจะถูกจับคู่ในตารางอื่นหรือไม่:
select
a.brand
from
brands a
left outer join cars b
on a.ID=b.brand
group by
a.brand
+--------+
| brand |
+--------+
| BMW |
| Ford |
| Holden |
| Nissan |
| Smart |
| Toyota |
+--------+
6 rows in set (0.00 sec)
ตอนนี้เรามีสิ่งนั้นแล้วเราสามารถเพิ่มฟังก์ชั่นการรวมที่น่ารักเพื่อการนับและกำจัดหัวหน้าของเราสักครู่
select
a.brand,
count(b.id) as countOfBrand
from
brands a
left outer join cars b
on a.ID=b.brand
group by
a.brand
+--------+--------------+
| brand | countOfBrand |
+--------+--------------+
| BMW | 2 |
| Ford | 2 |
| Holden | 0 |
| Nissan | 1 |
| Smart | 1 |
| Toyota | 5 |
+--------+--------------+
6 rows in set (0.00 sec)
และด้วยสิ่งนั้นให้ห่างจากเจ้านาย
ตอนนี้หากต้องการอธิบายรายละเอียดเพิ่มเติมบางอย่างการรวมภายนอกอาจเป็นประเภทleft
หรือ right
ซ้ายหรือขวากำหนดตารางเป็นอย่างเต็มที่รวม A left outer join
จะรวมแถวทั้งหมดจากตารางทางด้านซ้ายในขณะที่ (คุณเดา) right outer join
จะนำผลลัพธ์ทั้งหมดจากตารางด้านขวาไปยังผลลัพธ์
ฐานข้อมูลบางอย่างจะอนุญาตให้ใช้full outer join
ซึ่งจะนำผลลัพธ์กลับมา (ไม่ว่าจะตรงกันหรือไม่ก็ตาม) จากทั้งสองตาราง แต่ไม่รองรับในฐานข้อมูลทั้งหมด
ตอนนี้ฉันอาจคิดว่า ณ เวลานี้คุณกำลังสงสัยว่าคุณสามารถผสานประเภทการเข้าร่วมในแบบสอบถามได้หรือไม่และคำตอบคือใช่คุณทำได้จริง ๆ
select
b.brand,
c.color,
count(a.id) as countOfBrand
from
cars a
right outer join brands b
on b.ID=a.brand
join colors c
on a.color=c.ID
group by
a.brand,
c.color
+--------+-------+--------------+
| brand | color | countOfBrand |
+--------+-------+--------------+
| Ford | Blue | 1 |
| Ford | White | 1 |
| Toyota | Black | 1 |
| Toyota | Green | 2 |
| Toyota | Red | 1 |
| Nissan | Black | 1 |
| Smart | White | 1 |
| BMW | Blue | 1 |
| BMW | White | 1 |
+--------+-------+--------------+
9 rows in set (0.00 sec)
เหตุใดจึงไม่ผลลัพธ์ที่คาดไว้ เป็นเพราะแม้ว่าเราได้เลือกการรวมภายนอกจากรถยนต์ไปยังแบรนด์ แต่ไม่ได้ระบุในการเข้าร่วมสีดังนั้นการเข้าร่วมโดยเฉพาะจะนำผลลัพธ์ที่ตรงกันในทั้งสองตารางกลับมาใช้
นี่คือข้อความค้นหาที่ใช้งานเพื่อให้ได้ผลลัพธ์ตามที่เราคาดไว้:
select
a.brand,
c.color,
count(b.id) as countOfBrand
from
brands a
left outer join cars b
on a.ID=b.brand
left outer join colors c
on b.color=c.ID
group by
a.brand,
c.color
+--------+-------+--------------+
| brand | color | countOfBrand |
+--------+-------+--------------+
| BMW | Blue | 1 |
| BMW | White | 1 |
| Ford | Blue | 1 |
| Ford | White | 1 |
| Holden | NULL | 0 |
| Nissan | Black | 1 |
| Smart | White | 1 |
| Toyota | NULL | 1 |
| Toyota | Black | 1 |
| Toyota | Green | 2 |
| Toyota | Red | 1 |
+--------+-------+--------------+
11 rows in set (0.00 sec)
อย่างที่เราเห็นเรามีตัวเชื่อมภายนอกสองตัวในแบบสอบถามและผลลัพธ์จะผ่านตามที่คาดไว้
ทีนี้คุณคิดว่าคุณจะเข้าร่วมประเภทไหนได้บ้าง สิ่งที่เกี่ยวกับการแยก?
ไม่ใช่ฐานข้อมูลทั้งหมดที่สนับสนุนintersection
แต่ฐานข้อมูลทั้งหมดจะช่วยให้คุณสร้างจุดตัดผ่านการเข้าร่วม (หรือโครงสร้างที่ดีที่มีคำสั่งอย่างน้อย)
Intersection เป็นประเภทของการเข้าร่วมที่ค่อนข้างคล้ายกับunion
ที่อธิบายไว้ข้างต้น - แต่ความแตกต่างคือมันจะส่งกลับเฉพาะแถวของข้อมูลที่เหมือนกัน (และฉันหมายถึงเหมือนกัน) ระหว่างแบบสอบถามแบบต่างๆที่เข้าร่วมโดยสหภาพ จะส่งคืนเฉพาะแถวที่เหมือนกันทุกประการ
ตัวอย่างง่ายๆจะเป็นเช่นนี้:
select
*
from
colors
where
ID>2
intersect
select
*
from
colors
where
id<4
ในขณะที่union
แบบสอบถามปกติจะส่งกลับแถวทั้งหมดของตาราง (แบบสอบถามแรกที่ส่งคืนสิ่งใด ๆID>2
และรายการที่สองมีID<4
) ซึ่งจะส่งผลให้ครบชุดแบบสอบถามตัดกันจะส่งคืนการจับคู่แถวid=3
ตามที่ตรงกับเกณฑ์ทั้งสองเท่านั้น
ตอนนี้ถ้าฐานข้อมูลของคุณไม่รองรับการintersect
สืบค้นข้อมูลข้างต้นสามารถใช้งานได้อย่างง่ายดายด้วยการสืบค้นดังต่อไปนี้:
select
a.ID,
a.color,
a.paint
from
colors a
join colors b
on a.ID=b.ID
where
a.ID>2
and b.ID<4
+----+-------+----------+
| ID | color | paint |
+----+-------+----------+
| 3 | Blue | Metallic |
+----+-------+----------+
1 row in set (0.00 sec)
หากคุณต้องการดำเนินการทางแยกข้ามสองตารางที่แตกต่างกันโดยใช้ฐานข้อมูลที่ไม่สนับสนุนการค้นหาทางแยกคุณจะต้องสร้างการเข้าร่วมในทุกคอลัมน์ของตาราง