อะไรคือความแตกต่างระหว่างการเข้าร่วมแบบธรรมชาติและการเข้าร่วมแบบภายใน?
อะไรคือความแตกต่างระหว่างการเข้าร่วมแบบธรรมชาติและการเข้าร่วมแบบภายใน?
คำตอบ:
ความแตกต่างที่สำคัญอย่างหนึ่งระหว่าง INNER JOIN และ NATURAL JOIN คือจำนวนคอลัมน์ที่ส่งคืน
พิจารณา:
TableA TableB
+------------+----------+ +--------------------+
|Column1 | Column2 | |Column1 | Column3 |
+-----------------------+ +--------------------+
| 1 | 2 | | 1 | 3 |
+------------+----------+ +---------+----------+
The INNER JOIN
ของ TableA และ TableB บน Column1 จะกลับมา
SELECT * FROM TableA AS a INNER JOIN TableB AS b USING (Column1);
SELECT * FROM TableA AS a INNER JOIN TableB AS b ON a.Column1 = b.Column1;
+------------+-----------+---------------------+
| a.Column1 | a.Column2 | b.Column1| b.Column3|
+------------------------+---------------------+
| 1 | 2 | 1 | 3 |
+------------+-----------+----------+----------+
The NATURAL JOIN
ของ TableA และ TableB บน Column1 จะกลับมา:
SELECT * FROM TableA NATURAL JOIN TableB
+------------+----------+----------+
|Column1 | Column2 | Column3 |
+-----------------------+----------+
| 1 | 2 | 3 |
+------------+----------+----------+
หลีกเลี่ยงคอลัมน์ซ้ำ ๆ
(AFAICT จากไวยากรณ์มาตรฐานคุณไม่สามารถระบุคอลัมน์การเข้าร่วมในการเข้าร่วมแบบธรรมชาติการเข้าร่วมเป็นไปตามชื่ออย่างเคร่งครัดดูเพิ่มเติมที่Wikipedia )
( มีการโกงในด้านเอาท์พุทเข้าร่วมนั้นa.
และb.
ชิ้นส่วนจะไม่อยู่ในชื่อคอลัมน์ที่คุณต้องการเพียงแค่มีcolumn1
, column2
, column1
, column3
เป็นหัว. )
NATURAL JOIN
จะทำลายว่าทำไมมันไม่คาดคิดและโลกที่คุณอยู่ใน?
Customers
และเข้าร่วมใน Employees
ยังมีเขตข้อมูล ทุกอย่างเรียบร้อยดี. จากนั้นสักวันมีคนเพิ่มเขตข้อมูลลงในตาราง การเข้าร่วมของคุณจะไม่แตก (นั่นคือความเมตตา) แต่จะรวมฟิลด์ที่สองและทำงานอย่างไม่ถูกต้องแทน ดังนั้นการเปลี่ยนแปลงที่ไม่เป็นอันตรายดูเหมือนจะทำลายบางสิ่งบางอย่างที่เกี่ยวข้องในระยะไกลเท่านั้น ที่เลวร้ายมาก. ข้อเสียของการเข้าร่วมที่เป็นธรรมชาติเพียงอย่างเดียวคือการประหยัดการพิมพ์เพียงเล็กน้อยและข้อเสียคือสิ่งสำคัญ EmployeeID
Employees
ManagerID
ManagerID
Customers
SELECT * FROM TableA INNER JOIN TableB USING (Column1)
4 คอลัมน์ สิ่งนี้ไม่ถูกต้องเพราะSELECT * FROM TableA INNER JOIN TableB USING (Column1)
และSELECT * FROM TableA NATURAL JOIN TableB
เท่ากันพวกเขาทั้งสองให้ 3 คอลัมน์
natural left
หรือnatural right
) ที่ถือว่าเกณฑ์การเข้าร่วมเป็นคอลัมน์ที่มีชื่อเดียวกันในการจับคู่ทั้งสองตารางฉันจะหลีกเลี่ยงการใช้การรวมธรรมชาติอย่างกาฬโรคเพราะการรวมธรรมชาติคือ:
NATURAL JOIN Checkouts
"ที่ดูไม่เป็นทางการนั้นเป็นไปได้ก็ต่อเมื่อการตั้งชื่อฐานข้อมูลเป็นระเบียบและบังคับใช้อย่างเป็นทางการ .... "
id
แพร่หลายและไร้ประโยชน์ในการเข้าร่วม tablename_id
ปกติชื่อคีย์ต่างประเทศ การรวมตามธรรมชาติเป็นความคิดที่เลวร้ายเลวและเลว
การเข้าร่วมแบบธรรมชาติเป็นเพียงทางลัดเพื่อหลีกเลี่ยงการพิมพ์โดยมีข้อสันนิษฐานว่าการเข้าร่วมนั้นง่ายและจับคู่ฟิลด์ที่มีชื่อเดียวกัน
SELECT
*
FROM
table1
NATURAL JOIN
table2
-- implicitly uses `room_number` to join
เหมือนกับ ...
SELECT
*
FROM
table1
INNER JOIN
table2
ON table1.room_number = table2.room_number
สิ่งที่คุณทำไม่ได้กับรูปแบบทางลัดมีความซับซ้อนมากกว่า ...
SELECT
*
FROM
table1
INNER JOIN
table2
ON (table1.room_number = table2.room_number)
OR (table1.room_number IS NULL AND table2.room_number IS NULL)
NATURAL JOIN ... USING ()
ไม่ได้มาตรฐานนี้: มาตรฐานเป็นa NATURAL JOIN b
หรือa JOIN b USING (c)
room_number
room_number
SQL ไม่ซื่อสัตย์กับโมเดลเชิงสัมพันธ์ในหลาย ๆ ด้าน ผลลัพธ์ของการสืบค้น SQL ไม่ใช่ความสัมพันธ์เนื่องจากอาจมีคอลัมน์ที่มีชื่อซ้ำกัน, 'นิรนาม' (ไม่ระบุชื่อ) คอลัมน์, แถวซ้ำ, โมฆะ ฯลฯ SQL ไม่ถือว่าตารางเป็นความสัมพันธ์เนื่องจากอาศัยการเรียงลำดับคอลัมน์เป็นต้น
แนวคิดเบื้องหลังNATURAL JOIN
ใน SQL คือการทำให้ซื่อสัตย์ต่อโมเดลเชิงสัมพันธ์ได้ง่ายขึ้น ผลลัพธ์ของNATURAL JOIN
ทั้งสองตารางจะมีการทำซ้ำคอลัมน์ตามชื่อจึงไม่มีคอลัมน์ที่ไม่ระบุชื่อ ในทำนองเดียวกันUNION CORRESPONDING
และEXCEPT CORRESPONDING
มีไว้เพื่อจัดการกับการพึ่งพาของ SQL ในการเรียงลำดับคอลัมน์ในUNION
ไวยากรณ์ดั้งเดิม
อย่างไรก็ตามเช่นเดียวกับเทคนิคการเขียนโปรแกรมทั้งหมดมันต้องมีระเบียบวินัยที่จะเป็นประโยชน์ ข้อกำหนดหนึ่งสำหรับการประสบความสำเร็จNATURAL JOIN
คือการตั้งชื่อคอลัมน์อย่างสม่ำเสมอเนื่องจากการรวมจะบอกเป็นนัยในคอลัมน์ที่มีชื่อเดียวกัน (มันเป็นความอัปยศที่ไวยากรณ์สำหรับการเปลี่ยนชื่อคอลัมน์ใน SQL นั้นเป็น verbose แต่ผลข้างเคียงคือการส่งเสริมวินัยเมื่อตั้งชื่อคอลัมน์ในตารางฐานและVIEW
s :)
หมายเหตุ SQL NATURAL JOIN
คือการเข้าร่วม equi แต่นี่ไม่ใช่บาร์สำหรับประโยชน์ พิจารณาว่าหากNATURAL JOIN
เป็นชนิดการรวมเท่านั้นที่ได้รับการสนับสนุนใน SQL มันจะยังคงสมบูรณ์แบบสัมพันธ์กัน
ในขณะที่มันเป็นความจริงที่ใด ๆ ที่NATURAL JOIN
อาจถูกเขียนโดยใช้INNER JOIN
และประมาณการ ( SELECT
) มันก็เป็นความจริงที่ใด ๆ ที่INNER JOIN
อาจถูกเขียนโดยใช้ผลิตภัณฑ์ ( CROSS JOIN
) และข้อ จำกัด ( WHERE
); ทราบเพิ่มเติมว่าระหว่างตารางที่ไม่มีชื่อคอลัมน์ในการร่วมกันจะให้ผลเช่นเดียวกับNATURAL JOIN
CROSS JOIN
ดังนั้นหากคุณสนใจเฉพาะผลลัพธ์ที่มีความสัมพันธ์ (และทำไมไม่เคย?!) ดังนั้นจึงNATURAL JOIN
เป็นประเภทการเข้าร่วมเพียงอย่างเดียวที่คุณต้องการ แน่นอนว่ามันเป็นความจริงที่มาจากมุมมองการออกแบบภาษาเช่นINNER JOIN
และCROSS JOIN
มีค่าของพวกเขา แต่ยังพิจารณาว่าเกือบทุกแบบสอบถาม SQL สามารถเขียนใน 10 syntactically แตกต่างกัน แต่วิธีที่เท่าเทียมกันทางความหมายและนี่คือสิ่งที่ทำให้เพิ่มประสิทธิภาพ SQL ยากมาก เพื่อพัฒนา.
ต่อไปนี้เป็นตัวอย่างแบบสอบถาม (ใช้ชิ้นส่วนปกติและฐานข้อมูลผู้จัดหา ) ที่เทียบเท่ากับความหมาย:
SELECT *
FROM S NATURAL JOIN SP;
-- Must disambiguate and 'project away' duplicate SNO attribute
SELECT S.SNO, SNAME, STATUS, CITY, PNO, QTY
FROM S INNER JOIN SP
USING (SNO);
-- Alternative projection
SELECT S.*, PNO, QTY
FROM S INNER JOIN SP
ON S.SNO = SP.SNO;
-- Same columns, different order == equivalent?!
SELECT SP.*, S.SNAME, S.STATUS, S.CITY
FROM S INNER JOIN SP
ON S.SNO = SP.SNO;
-- 'Old school'
SELECT S.*, PNO, QTY
FROM S, SP
WHERE S.SNO = SP.SNO;
** การรวมเข้าด้วยกันแบบสัมพันธ์นั้นไม่ได้เป็น equijoin แต่เป็นการคาดการณ์หนึ่ง - ฟิลิปซี่
การNATURAL
เข้าร่วมเป็นเพียงไวยากรณ์สั้น ๆ สำหรับการเข้าร่วมที่เฉพาะเจาะจง INNER
- หรือ "การเข้าร่วม equi" - และเมื่อไวยากรณ์ไม่ได้เปิดใช้แล้วทั้งคู่จะเป็นตัวแทนของการดำเนินงานพีชคณิตเชิงสัมพันธ์แบบเดียวกัน มันไม่ใช่ "การเข้าร่วมที่แตกต่าง" เช่นเดียวกับกรณีของOUTER
( LEFT
/ RIGHT
) หรือการCROSS
เข้าร่วม
ดูส่วนequi-joinใน Wikipedia:
การเข้าร่วมที่เป็นธรรมชาติมอบความเชี่ยวชาญเพิ่มเติมให้กับ equi-joins เข้าร่วมกริยาเกิดขึ้นโดยปริยายโดยการเปรียบเทียบคอลัมน์ทั้งหมดในตารางทั้งสองที่มีชื่อคอลัมน์เดียวกันในตารางที่เข้าร่วม ตารางการรวมผลลัพธ์มีเพียงหนึ่งคอลัมน์สำหรับแต่ละคอลัมน์ที่มีชื่อเท่ากัน
ผู้เชี่ยวชาญส่วนใหญ่เห็นพ้องกันว่าการเข้าร่วมตามธรรมชาตินั้นมีอันตรายและไม่สนับสนุนการใช้งานของพวกเขาอย่างยิ่ง อันตรายมาจากการเพิ่มคอลัมน์ใหม่โดยไม่ได้ตั้งใจตั้งชื่อเหมือนกับคอลัมน์อื่น ...
นั่นคือการรวมทั้งหมดNATURAL
อาจถูกเขียนเป็นตัวINNER
เชื่อม (แต่การสนทนาไม่เป็นความจริง) ในการทำเช่นนั้นเพียงสร้างภาคแสดงอย่างชัดเจน - USING
หรือON
- และตามที่ Jonathan Leffler ชี้ให้เลือกคอลัมน์ชุดผลลัพธ์ที่ต้องการเพื่อหลีกเลี่ยง "ซ้ำ" หากต้องการ
การเข้ารหัสที่มีความสุข
( NATURAL
คำหลักสามารถนำไปใช้กับLEFT
และRIGHT
รวมได้เช่นเดียวกันการNATURAL LEFT/RIGHT
เข้าร่วมเป็นเพียงไวยากรณ์สั้น ๆ สำหรับการเข้าร่วมที่เฉพาะเจาะจง LEFT/RIGHT
)
เข้าร่วมธรรมชาติ: มันคือการรวมหรือผลรวมของคอลัมน์ทั้งหมดในสองตาราง มันจะส่งคืนแถวทั้งหมดของตารางแรกที่เกี่ยวกับตารางที่สอง
Inner Join: การเข้าร่วมนี้จะใช้งานได้หากไม่มีชื่อคอลัมน์ใด ๆ จะเป็น sxame ในสองตาราง
การเข้าร่วมแบบธรรมชาติคือตำแหน่งที่มีการรวมตาราง 2 ตารางบนพื้นฐานของคอลัมน์ทั่วไปทั้งหมด
common column: เป็นคอลัมน์ที่มีชื่อเหมือนกันในทั้งสองตาราง + มีประเภทข้อมูลที่เข้ากันได้ในทั้งสองตาราง คุณสามารถใช้ตัวดำเนินการ = เท่านั้น
การรวมภายในคือที่ 2 ตารางจะถูกรวมเข้าด้วยกันบนพื้นฐานของคอลัมน์ทั่วไปที่กล่าวถึงในส่วนคำสั่ง ON
common column: เป็นคอลัมน์ที่มีประเภทข้อมูลที่เข้ากันได้ในทั้งสองตาราง แต่ไม่จำเป็นต้องมีชื่อเดียวกัน คุณสามารถใช้เฉพาะผู้ประกอบการเปรียบเทียบใด ๆ เช่น=
, <=
, >=
, <
, >
,<>
ความแตกต่างคือการเข้าร่วม int (equi / default) และการเข้าร่วมแบบธรรมชาติที่อยู่ในการเข้าร่วม natuarl คอลัมน์ทั่วไปที่ชนะจะแสดงในครั้งเดียว แต่การเข้าร่วมภายใน / equi / default / ง่ายคอลัมน์ทั่วไปจะแสดงสองครั้ง
การรวมภายในและการเข้าร่วมแบบธรรมชาติเกือบจะเหมือนกัน แต่มีความแตกต่างเล็กน้อยระหว่างพวกเขา ความแตกต่างอยู่ในการเข้าร่วมที่เป็นธรรมชาติไม่จำเป็นต้องระบุเงื่อนไข แต่ในเงื่อนไขการรวมภายในเป็นข้อบังคับ หากเราระบุเงื่อนไขในการรวมภายในตารางผลลัพธ์จะเหมือนกับผลิตภัณฑ์คาร์ทีเซียน
mysql> SELECT * FROM tb1 ;
+----+------+
| id | num |
+----+------+
| 6 | 60 |
| 7 | 70 |
| 8 | 80 |
| 1 | 1 |
| 2 | 2 |
| 3 | 3 |
+----+------+
6 rows in set (0.00 sec)
mysql> SELECT * FROM tb2 ;
+----+------+
| id | num |
+----+------+
| 4 | 40 |
| 5 | 50 |
| 9 | 90 |
| 1 | 1 |
| 2 | 2 |
| 3 | 3 |
+----+------+
6 rows in set (0.00 sec)
เข้าร่วมภายใน:
mysql> SELECT * FROM tb1 JOIN tb2 ;
+----+------+----+------+
| id | num | id | num |
+----+------+----+------+
| 6 | 60 | 4 | 40 |
| 7 | 70 | 4 | 40 |
| 8 | 80 | 4 | 40 |
| 1 | 1 | 4 | 40 |
| 2 | 2 | 4 | 40 |
| 3 | 3 | 4 | 40 |
| 6 | 60 | 5 | 50 |
| 7 | 70 | 5 | 50 |
| 8 | 80 | 5 | 50 |
.......more......
return 36 rows in set (0.01 sec)
AND NATURAL JOIN :
mysql> SELECT * FROM tb1 NATURAL JOIN tb2 ;
+----+------+
| id | num |
+----+------+
| 1 | 1 |
| 2 | 2 |
| 3 | 3 |
+----+------+
3 rows in set (0.01 sec)
Inner join, เข้าร่วมสองตารางที่ชื่อคอลัมน์เหมือนกัน
การเข้าร่วมแบบธรรมชาติเข้าร่วมสองตารางที่ชื่อคอลัมน์และชนิดข้อมูลเหมือนกัน