SQL-4.1 INNER JOIN
INNER JOIN คือ “จุดตัด” ของสองตาราง — ถ้าแถวไหนไม่มีคู่ match ก็จะไม่ปรากฏในผลลัพธ์เลย
แนวคิดหลัก
Section titled “แนวคิดหลัก”INNER JOIN ดึงเฉพาะแถวที่มีค่าตรงกันในทั้งสองตาราง เหมือนการหา intersection ของ 2 เซ็ต
students enrollments┌─────────┐ ┌─────────────┐│ STD001 │──────▶│ STD001 │ ✅ match → ปรากฏในผลลัพธ์│ STD002 │──────▶│ STD002 │ ✅ match → ปรากฏในผลลัพธ์│ STD003 │ ✗ │ │ ❌ ไม่มี match → หายไป│ │ │ STD999 │ ❌ ไม่มี match → หายไป└─────────┘ └─────────────┘ตัวอย่างจริง
Section titled “ตัวอย่างจริง”-- สร้างตารางCREATE TABLE students ( student_id VARCHAR(6) PRIMARY KEY, name VARCHAR(100), email VARCHAR(100));
CREATE TABLE enrollments ( enrollment_id SERIAL PRIMARY KEY, student_id VARCHAR(6), course_id VARCHAR(6), enrolled_on DATE);
INSERT INTO students VALUES ('STD001', 'สมชาย', 'somchai@mail.com');INSERT INTO students VALUES ('STD002', 'สมหญิง', 'somying@mail.com');INSERT INTO students VALUES ('STD003', 'วิชัย', 'wichai@mail.com');
INSERT INTO enrollments VALUES (1, 'STD001', 'CS101', '2025-08-15');INSERT INTO enrollments VALUES (2, 'STD001', 'CS102', '2025-08-16');INSERT INTO enrollments VALUES (3, 'STD002', 'CS101', '2025-08-15');
-- INNER JOIN: เฉพาะนักเรียนที่มีการลงทะเบียนSELECT s.student_id, s.name, e.course_id, e.enrolled_onFROM students sINNER JOIN enrollments e ON s.student_id = e.student_id;ผลลัพธ์: 3 แถว — STD001 (2 วิชา) + STD002 (1 วิชา)
สังเกต: STD003 (วิชัย) หายไป เพราะไม่มี enrollment
เทียบกับ WHERE เก่า (Implicit Join):
-- แบบเก่า (ยังใช้ได้ แต่ไม่แนะนำ)SELECT s.name, e.course_idFROM students s, enrollments eWHERE s.student_id = e.student_id;
-- แบบใหม่ (ชัดเจนกว่า)SELECT s.name, e.course_idFROM students sINNER JOIN enrollments e ON s.student_id = e.student_id;ใน Sheets ใช้ VLOOKUP หรือ INDEX/MATCH ซึ่งทำงานคล้าย INNER JOIN:
=VLOOKUP(A2, enrollments!A:C, 3, FALSE)ถ้าหาไม่เจอจะได้ #N/A — ซึ่งก็คือ “ไม่มี match” เหมือน INNER JOIN
import pandas as pd
students = pd.DataFrame({ 'student_id': ['STD001', 'STD002', 'STD003'], 'name': ['สมชาย', 'สมหญิง', 'วิชัย']})enrollments = pd.DataFrame({ 'student_id': ['STD001', 'STD001', 'STD002'], 'course_id': ['CS101', 'CS102', 'CS101']})
# inner join — default ของ mergeresult = students.merge(enrollments, on='student_id', how='inner')print(result)# STD003 หายไป เหมือน SQL#include <stdio.h>#include <string.h>
// INNER JOIN = nested loop ที่เช็ค matchint main() { char *students[] = {"STD001", "STD002", "STD003"}; char *names[] = {"สมชาย", "สมหญิง", "วิชัย"}; char *enroll_sid[] = {"STD001", "STD001", "STD002"}; char *enroll_cid[] = {"CS101", "CS102", "CS101"};
for (int s = 0; s < 3; s++) { for (int e = 0; e < 3; e++) { if (strcmp(students[s], enroll_sid[e]) == 0) { printf("%s %s %s\n", students[s], names[s], enroll_cid[e]); } } } return 0;}C แสดงให้เห็นว่า JOIN คือ nested loop + comparison เบื้องหลัง
| สิ่งที่ต้องจำ | รายละเอียด |
|---|---|
INNER JOIN | ดึงเฉพาะแถวที่ match ทั้งสองฝั่ง |
ON clause | กำหนดเงื่อนไขการเชื่อม (มักเป็น primary key = foreign key) |
| ไม่มี match | แถวนั้นหายไปจากผลลัพธ์ |
Alias (s, e) | ใช้ตัวย่อเพื่อให้อ่านง่าย |