[เริ่มต้นกับ SQL] มาเป็นเจ้าแห่งเงื่อนไขซับซ้อน! พิชิต AND, OR, NOT ให้เชี่ยวชาญ
"อยากดึงข้อมูลเฉพาะจากฐานข้อมูล แต่เงื่อนไขเดียวไม่พอ..."
ในฐานะเว็บครีเอเตอร์ที่กำลังพัฒนาฝีมือ คุณเคยเจอกำแพงแบบนี้บ้างไหมครับ?
SQL คือภาษาสำหรับจัดการฐานข้อมูล และคำสั่ง SELECT ที่ใช้ดึงข้อมูลก็ถือเป็นพื้นฐานที่สุด แต่การจะเจาะจงข้อมูลที่ต้องการจริงๆ นั้น เทคนิคการผสมผสานหลายเงื่อนไขเพื่อกรองข้อมูลเป็นสิ่งที่ขาดไม่ได้เลย
ในบทความนี้ เราจะอธิบายวิธีการใช้ 3 ตัวดำเนินการตรรกะ (Logical Operators) สำหรับกำหนดเงื่อนไขซับซ้อน ได้แก่ AND, OR, และ NOT อย่างละเอียด พร้อมโค้ดตัวอย่างที่แม้แต่มือใหม่ก็สามารถคัดลอกไปใช้ได้ทันที! มาสัมผัสประสบการณ์ "โค้ดรันได้!" เพื่อเรียนรู้ความสนุกและความสะดวกของ SQL ไปด้วยกันนะครับ
การเตรียมตัว: มาสร้างตารางสำหรับฝึกฝนกันเถอะ!
ก่อนอื่น เรามาสร้างตารางสำหรับฝึกฝนในบทความนี้กันครับ เป็นตารางชื่อ employees ที่เก็บข้อมูลพนักงานสมมติขึ้นมา ลองคัดลอกโค้d SQL ด้านล่างแล้วนำไปรันในระบบฐานข้อมูลของคุณได้เลย
แต่ถ้ายังไม่มีสภาพแวดล้อมสำหรับทดลองก็ไม่ต้องกังวล! ในช่วงท้ายของบทความ เราได้เตรียม "สนามฝึก SQL" ที่ให้คุณสามารถลองเขียน SQL บนเบราว์เซอร์ได้เลย ดังนั้นตอนนี้อ่านต่อไปก่อนได้เลยครับ
-- ลบตารางหากมีอยู่แล้ว
DROP TABLE IF EXISTS employees;
-- สร้างตาราง employees
CREATE TABLE employees (
id INT PRIMARY KEY,
name VARCHAR(50),
department VARCHAR(50),
position VARCHAR(50),
salary INT,
hire_date DATE
);
-- เพิ่มข้อมูล
INSERT INTO employees (id, name, department, position, salary, hire_date) VALUES
(1, '山田 太郎', '営業部', 'マネージャー', 600000, '2018-04-01'),
(2, '鈴木 花子', '開発部', 'エンジニア', 550000, '2020-10-01'),
(3, '佐藤 次郎', '営業部', 'スタッフ', 400000, '2022-04-01'),
(4, '高橋 三郎', '人事部', 'マネージャー', 650000, '2017-07-01'),
(5, '田中 恵子', '開発部', 'デザイナー', 500000, '2021-08-15'),
(6, '伊藤 四郎', '営業部', 'マネージャー', 700000, '2015-02-01'),
(7, '渡辺 久美', '開発部', 'エンジニア', 750000, '2019-06-01'),
(8, '山本 五郎', '人事部', 'スタッフ', 380000, '2023-04-01'),
(9, '中村 さくら', '開発部', 'マネージャー', 800000, '2016-09-01'),
(10, '小林 健太', '営業部', 'スタッフ', 420000, '2023-10-01');
เตรียมพร้อมกันแล้วหรือยังครับ? เรามาตะลุยโลกแห่งการกำหนดเงื่อนไขด้วยตารางนี้กันเลย!
1. AND: การเจาะจงข้อมูลที่ตรงตามทุกเงื่อนไข!
AND ในภาษาไทยคือ "และ" ใช้เมื่อต้องการดึงข้อมูลที่ตรงตามเงื่อนไขทั้งหมดที่ระบุเท่านั้น
ตัวอย่างเช่น กรณีที่ต้องการข้อมูลพนักงานที่ "สังกัดแผนกขาย" และ "มีตำแหน่งเป็นผู้จัดการ"
วิธีใช้พื้นฐาน
เราจะเชื่อมเงื่อนไขต่างๆ ด้วย AND ภายใน WHERE clause
SELECT *
FROM employees
WHERE department = '営業部' AND position = 'マネージャー';
เมื่อรัน SQL นี้ จะได้ข้อมูลของพนักงานที่มี department เป็น '営業部' (แผนกขาย) และ มี position เป็น 'マネージャー' (ผู้จัดการ) ทั้งหมด ซึ่งก็คือคุณยามาดะและคุณอิโต
การเชื่อม AND หลายตัว
เราสามารถเชื่อม AND กี่ตัวก็ได้ ยิ่งเพิ่มเงื่อนไขมากเท่าไร ข้อมูลก็จะยิ่งถูกกรองให้แคบลงเท่านั้น
ตัวอย่างเช่น ลองค้นหาพนักงานที่ "สังกัดแผนกขาย" และ "มีตำแหน่งเป็นผู้จัดการ" และ "มีเงินเดือนตั้งแต่ 650,000 ขึ้นไป"
SELECT *
FROM employees
WHERE
department = '営業部'
AND position = 'マネージャー'
AND salary >= 650000;
ครั้งนี้จะเห็นว่ามีแค่คุณอิโตคนเดียวที่แสดงผล เพราะการเพิ่มเงื่อนไขทำให้คุณยามาดะถูกตัดออกไป จะเห็นว่า AND มีประโยชน์มากในการเจาะจงข้อมูลที่ต้องการโดยการซ้อนเงื่อนไขเข้าไป
2. OR: การดึงข้อมูลที่ตรงตามเงื่อนไขใดเงื่อนไขหนึ่ง!
OR คือ "หรือ" ใช้เมื่อต้องการดึงข้อมูลที่ตรงตามเงื่อนไขอย่างน้อยหนึ่งข้อจากที่ระบุไว้
จะมีประโยชน์ในกรณีที่ต้องการรายชื่อพนักงานที่ "สังกัดแผนกขาย" หรือ "สังกัดแผนกพัฒนา"
วิธีใช้พื้นฐาน
วิธีใช้เหมือนกับ AND คือเชื่อมเงื่อนไขด้วย OR ใน WHERE clause
SELECT *
FROM employees
WHERE department = '営業部' OR department = '開発部';
เมื่อรันคำสั่งนี้ พนักงานจากแผนก '営業部' (แผนกขาย) และแผนก '開発部' (แผนกพัฒนา) ทั้งหมดจะถูกแสดงผล ในขณะที่ AND จะกรองข้อมูลให้แคบลง OR จะมีภาพลักษณ์เหมือนการเพิ่มข้อมูลที่ตรงตามเงื่อนไขเข้ามาเรื่อยๆ
การเชื่อม OR หลายตัว
แน่นอนว่า OR ก็สามารถเชื่อมหลายตัวได้เช่นกัน ลองค้นหาพนักงานที่ "มีตำแหน่งเป็นผู้จัดการ" หรือ "มีเงินเดือนตั้งแต่ 700,000 ขึ้นไป"
SELECT *
FROM employees
WHERE position = 'マネージャー' OR salary >= 700000;
ผลลัพธ์นี้จะประกอบด้วย:
- คนที่เป็นผู้จัดการ (คุณยามาดะ, ทาคาฮาชิ, อิโต, นากามูระ)
- คนที่มีเงินเดือน 700,000 ขึ้นไป (คุณอิโต, วาตานาเบะ, นากามูระ)
คุณอิโตและคุณนากามูระตรงตามทั้งสองเงื่อนไข และแน่นอนว่าพวกเขาก็จะถูกรวมอยู่ในผลลัพธ์ด้วย OR เป็นการกำหนดเงื่อนไขแบบหลวมๆ ที่หมายความว่า "แค่ตรงตามเงื่อนไขข้อใดข้อหนึ่งก็พอ"
3. NOT: การคัดกรองข้อมูลที่ไม่ตรงตามเงื่อนไข!
NOT ตามชื่อเลยครับ ใช้กำหนดเงื่อนไขปฏิเสธว่า "ไม่ใช่..." มีประโยชน์เมื่อต้องการยกเว้นข้อมูลที่มีคุณสมบัติบางอย่างออกไป
วิธีใช้พื้นฐาน
วาง NOT ไว้หน้าเงื่อนไขที่ต้องการปฏิเสธใน WHERE clause
ตัวอย่างเช่น ลองดึงข้อมูลพนักงานทุกคนที่ไม่ใช่พนักงานใน "แผนกพัฒนา"
SELECT *
FROM employees
WHERE NOT department = '開発部';
เมื่อรันคำสั่งนี้ พนักงานที่อยู่นอกเหนือจากแผนก '開発部' (แผนกพัฒนา) ก็จะถูกแสดงผล ซึ่งก็คือพนักงานจาก '営業部' (แผนกขาย) และ '人事部' (แผนกบุคคล)
อีกอย่างคือ เราสามารถเขียนว่า WHERE department != '開発部' หรือ WHERE department <> '開発部' ก็ได้ผลลัพธ์เหมือนกัน จะเลือกใช้อันไหนก็ขึ้นอยู่กับความชอบหรือข้อตกลงของทีม แต่จุดเด่นของ NOT คือสามารถใช้ร่วมกับตัวดำเนินการอื่นๆ เช่น IN หรือ EXISTS ได้ ทำให้มีรูปแบบการใช้งานที่หลากหลายกว่า
[ขั้นสูง] การใช้ AND และ OR ร่วมกัน และความสำคัญของ "วงเล็บ"
เอาล่ะครับ ถึงช่วงของจริงแล้ว! การใช้ AND และ OR ร่วมกันจะทำให้เราสามารถกำหนดเงื่อนไขที่ซับซ้อนยิ่งขึ้นได้ แต่ตรงนี้มีกับดักใหญ่ที่มือใหม่มักจะพลาดกัน นั่นก็คือลำดับความสำคัญของตัวดำเนินการ
ใน SQL ถ้าหากไม่ได้กำหนดอะไรเป็นพิเศษ AND จะถูกประมวลผลก่อน OR เสมอ ซึ่งคล้ายกับการคำนวณทางคณิตศาสตร์ที่การคูณ (×) จะทำก่อนการบวก (+)
เพื่อให้ได้ข้อมูลตามที่ต้องการจริงๆ การใช้ () (วงเล็บ) เพื่อกำหนดลำดับความสำคัญให้ชัดเจนจึงเป็นเรื่องที่สำคัญอย่างยิ่ง เหมือนกับในวิชาคณิตศาสตร์เลยครับ
ตัวอย่างที่ไม่ดี: พนักงานที่อยู่ "แผนกขาย" หรือ "แผนกพัฒนา" และเป็น "ผู้จัดการ"?
หากเขียนเงื่อนไขนี้ไปตรงๆ โดยไม่คิดอะไรมาก อาจจะออกมาเป็นแบบนี้
-- SQL ที่ให้ผลลัพธ์ไม่ตรงตามที่ต้องการ
SELECT *
FROM employees
WHERE
department = '営業部'
OR department = '開発部' AND position = 'マネージャー';
ถ้าเรารัน SQL นี้ ผลลัพธ์จะเป็นอย่างไร?
เนื่องจาก AND มีความสำคัญสูงกว่า SQL จะประมวลผล department = '開発部' AND position = 'マネージャー' (ผู้จัดการในแผนกพัฒนา) ก่อน จากนั้นจึงนำผลลัพธ์นั้นไปเชื่อมกับ department = '営業部' (พนักงานทุกคนในแผนกขาย) ด้วย OR
พูดง่ายๆ ก็คือ Query นี้กำลังมองหา:
- ① พนักงานใน "แผนกขาย" (ทุกคนไม่ว่าตำแหน่งอะไร)
- ② พนักงานที่อยู่ "แผนกพัฒนา" และเป็น "ผู้จัดการ"
ซึ่งหมายถึงข้อมูลที่ตรงตามเงื่อนไขข้อใดข้อหนึ่งจากสองข้อนี้ ซึ่งไม่ตรงกับความตั้งใจเดิมของเราที่ต้องการ "ผู้จัดการที่อยู่แผนกขายหรือแผนกพัฒนา" ใช่ไหมครับ
ตัวอย่างที่ดี: จัดกลุ่มให้ถูกต้องด้วยวงเล็บ
เพื่อให้ได้เงื่อนไข "เป็นพนักงานในสังกัด (แผนกขาย หรือ แผนกพัฒนา) และมีตำแหน่งเป็นผู้จัดการ" ตามที่ตั้งใจไว้ เราจะต้องครอบส่วนที่เชื่อมด้วย OR ด้วยเครื่องหมาย ()
-- ใช้เครื่องหมายวงเล็บเพื่อให้ได้ผลลัพธ์ที่ถูกต้อง!
SELECT *
FROM employees
WHERE
(department = '営業部' OR department = '開発部')
AND position = 'マネージャー';
การทำเช่นนี้จะทำให้ (department = '営業部' OR department = '開発部') ถูกประมวลผลก่อน กลายเป็นกลุ่มเงื่อนไขก้อนเดียวที่หมายถึง "สังกัดแผนกขายหรือแผนกพัฒนา" จากนั้นเงื่อนไข AND position = 'マネージャー' จะถูกนำไปใช้กับผลลัพธ์นั้น ทำให้เราสามารถดึงข้อมูล "ผู้จัดการที่สังกัดแผนกขายหรือแผนกพัฒนา" ออกมาได้อย่างถูกต้อง
เมื่อใช้ AND และ OR ผสมกัน ต้องกำหนดลำดับความสำคัญด้วยวงเล็บ () เสมอ! จำข้อนี้ไว้เป็นกฎเหล็กเลยนะครับ!
ลงมือทำ! มาลองรัน SQL บนเบราว์เซอร์กัน
รอมานานแล้วใช่ไหมครับ! นี่คือของขวัญสำหรับทุกคน เป็นสภาพแวดล้อมที่คุณสามารถลงมือทดลองสิ่งที่เรียนมาทั้งหมดได้ด้วยตัวเอง
สิ่งนี้ถูกสร้างขึ้นโดยใช้ไลบรารี JavaScript (AlaSQL.js) เพื่อให้สามารถรัน SQL บนเบราว์เซอร์ได้ ลองคัดลอกโค้ดทั้งหมดด้านล่าง แล้วบันทึกเป็นไฟล์ชื่อ sql_practice.html จากนั้นเปิดไฟล์ด้วยเบราว์เซอร์ของคุณ
นำโค้ด SQL ต่างๆ ที่แนะนำในบทความนี้ไปวางในกล่องข้อความแล้วกดปุ่ม "รัน SQL" ผลลัพธ์ก็จะแสดงขึ้นมาทันที ลองเล่นดูเยอะๆ เพื่อสัมผัสกับการเปลี่ยนแปลงของข้อมูลได้เลยครับ!
<!DOCTYPE html>
<html lang="th">
<head>
<meta charset="UTF-8">
<title>สนามฝึก SQL</title>
<script src="https://cdn.jsdelivr.net/npm/alasql@4"></script>
<style>
body { font-family: sans-serif; padding: 2rem; background-color: #f9f9f9; }
.container { max-width: 800px; margin: auto; background: white; padding: 2rem; border-radius: 8px; box-shadow: 0 4px 8px rgba(0,0,0,0.1); }
h1 { color: #333; }
textarea { width: 100%; height: 150px; font-family: monospace; font-size: 16px; padding: 10px; border: 1px solid #ccc; border-radius: 4px; box-sizing: border-box; margin-bottom: 1rem; }
button { background-color: #007bff; color: white; padding: 10px 20px; border: none; border-radius: 4px; cursor: pointer; font-size: 16px; }
button:hover { background-color: #0056b3; }
#result-area { margin-top: 2rem; }
table { width: 100%; border-collapse: collapse; margin-top: 1rem; }
th, td { border: 1px solid #ddd; padding: 8px; text-align: left; }
th { background-color: #f2f2f2; }
.error { color: red; font-weight: bold; }
</style>
</head>
<body>
<div class="container">
<h1>มาลองใช้ SQL กันเถอะ!</h1>
<p>ป้อนคำสั่ง SQL ในกล่องข้อความด้านล่างแล้วกดปุ่ม "รัน SQL" มาลองใช้ SQL ที่หลากหลายที่เราได้แนะนำในบทความกัน!</p>
<textarea id="sql-input">-- เขียนโค้ด SQL ของคุณที่นี่
SELECT * FROM employees WHERE (department = '営業部' OR department = '開発部') AND position = 'マネージャー';</textarea>
<button onclick="executeSQL()">รัน SQL</button>
<div id="result-area"></div>
</div>
<script>
// การเตรียมข้อมูล
const createTableSQL = `
CREATE TABLE employees (
id INT, name STRING, department STRING, position STRING, salary INT, hire_date DATE
);
`;
const insertDataSQL = `
INSERT INTO employees VALUES
(1, '山田 太郎', '営業部', 'マネージャー', 600000, '2018-04-01'),
(2, '鈴木 花子', '開発部', 'エンジニア', 550000, '2020-10-01'),
(3, '佐藤 次郎', '営業部', 'スタッフ', 400000, '2022-04-01'),
(4, '高橋 三郎', '人事部', 'マネージャー', 650000, '2017-07-01'),
(5, '田中 恵子', '開発部', 'デザイナー', 500000, '2021-08-15'),
(6, '伊藤 四郎', '営業部', 'マネージャー', 700000, '2015-02-01'),
(7, '渡辺 久美', '開発部', 'エンジニア', 750000, '2019-06-01'),
(8, '山本 五郎', '人事部', 'スタッフ', 380000, '2023-04-01'),
(9, '中村 さくら', '開発部', 'マネージャー', 800000, '2016-09-01'),
(10, '小林 健太', '営業部', 'スタッフ', 420000, '2023-10-01');
`;
// เริ่มต้นฐานข้อมูล AlaSQL
const db = new alasql.Database();
db.exec(createTableSQL);
db.exec(insertDataSQL);
function executeSQL() {
const sql = document.getElementById('sql-input').value;
const resultArea = document.getElementById('result-area');
resultArea.innerHTML = ''; // ล้างผลลัพธ์ครั้งก่อน
try {
const result = db.exec(sql);
if (result.length > 0) {
resultArea.appendChild(createTable(result));
} else {
resultArea.innerHTML = '<p>ไม่พบผลลัพธ์ (0 แถว)</p>';
}
} catch (e) {
resultArea.innerHTML = `<p class="error">เกิดข้อผิดพลาด: ${e.message}</p>`;
}
}
function createTable(data) {
const table = document.createElement('table');
const thead = table.createTHead();
const tbody = table.createTBody();
const headerRow = thead.insertRow();
// สร้างหัวตาราง
for (const key in data[0]) {
const th = document.createElement('th');
th.textContent = key;
headerRow.appendChild(th);
}
// สร้างแถวข้อมูล
data.forEach(rowData => {
const row = tbody.insertRow();
for (const key in rowData) {
const cell = row.insertCell();
cell.textContent = rowData[key];
}
});
return table;
}
// แสดงผลครั้งแรก
executeSQL();
</script>
</body>
</html>
ข้อควรระวังและเทคนิคที่เกี่ยวข้อง
สุดท้ายนี้ เราจะมาแนะนำข้อควรระวังในการจัดการกับเงื่อนไขซับซ้อนและตัวดำเนินการที่มีประโยชน์อื่นๆ ที่เกี่ยวข้องครับ
การจัดการกับ NULL
ในฐานข้อมูลมีค่าพิเศษที่เรียกว่า NULL ซึ่งหมายถึง "ไม่มีข้อมูล" หรือสถานะว่างเปล่า
ข้อควรระวังคือ เราไม่สามารถเปรียบเทียบ NULL ด้วยเครื่องหมาย = หรือ != ได้ หากต้องการตรวจสอบว่าเป็น NULL หรือไม่ ต้องใช้คำสั่งเฉพาะคือ IS NULL หรือ IS NOT NULL
-- ค้นหาพนักงานที่ไม่มีข้อมูลเงินเดือน (เป็น NULL)
SELECT * FROM employees WHERE salary IS NULL;
-- ค้นหาพนักงานที่มีข้อมูลเงินเดือน (ไม่เป็น NULL)
SELECT * FROM employees WHERE salary IS NOT NULL;
ในข้อมูลตัวอย่างของเราไม่มีค่า NULL แต่ในการพัฒนาจริงจะเจอบ่อยมาก การเขียนว่า WHERE salary = NULL ถึงแม้จะไม่เกิด error แต่ก็จะไม่ให้ผลลัพธ์ตามที่ต้องการ ต้องระวังนะครับ
การกำหนดเงื่อนไขที่สะดวกยิ่งขึ้น: IN และ BETWEEN
บางครั้ง การเขียน OR หรือ AND เยอะๆ สามารถทำให้สั้นลงได้
IN: แทนที่ OR
ในกรณีที่ต้องการเชื่อมค่าหลายๆ ค่าสำหรับคอลัมน์เดียวกันด้วย OR เช่น "แผนกขาย, แผนกบุคคล หรือแผนกบัญชี" เราสามารถใช้ IN เพื่อให้โค้ดดูสะอาดตาขึ้น
-- วิธีเขียนแบบยาวโดยใช้ OR
SELECT * FROM employees
WHERE department = '営業部' OR department = '人事部';
-- วิธีเขียนแบบสั้นโดยใช้ IN
SELECT * FROM employees
WHERE department IN ('営業部', '人事部');
BETWEEN: แทนที่ AND
ในกรณีที่ต้องการกำหนดช่วงของตัวเลขหรือวันที่ เช่น "เงินเดือนตั้งแต่ 400,000 ถึง 600,000" การใช้ BETWEEN จะสะดวกกว่า
-- การกำหนดช่วงด้วย AND
SELECT * FROM employees
WHERE salary >= 400000 AND salary <= 600000;
-- การเขียนแบบสั้นโดยใช้ BETWEEN
SELECT * FROM employees
WHERE salary BETWEEN 400000 AND 600000;
แน่นอนว่าตัวดำเนินการเหล่านี้ก็สามารถใช้ร่วมกับ AND, OR, และ NOT ได้เช่นกัน การมีเทคนิคเหล่านี้ติดตัวไว้จะช่วยให้คุณเขียน SQL ได้ฉลาดขึ้นครับ
สรุป
お疲れ様でした!今回は、SQLで複数の条件を指定するための基本となるAND, OR, NOTについて、具体的な例を交えながら学びました。
- AND: "A และ B" เป็นจริงเมื่อทุกเงื่อนไขเป็นจริง ภาพลักษณ์คือการกรองให้แคบลง
- OR: "A หรือ B" เป็นจริงเมื่อเงื่อนไขใดเงื่อนไขหนึ่งเป็นจริง ภาพลักษณ์คือการขยายทางเลือก
- NOT: "ไม่ใช่..." กลับเงื่อนไข ภาพลักษณ์คือการยกเว้น
- การใช้ AND และ OR ร่วมกัน:
ANDมีความสำคัญสูงกว่า ดังนั้นการกำหนดลำดับด้วย()จึงสำคัญอย่างยิ่ง!
หากคุณเชี่ยวชาญตัวดำเนินการตรรกะเหล่านี้แล้ว คุณจะสามารถดึงข้อมูลได้ตามต้องการแม้ในเงื่อนไขที่ซับซ้อน และทักษะการจัดการข้อมูลของคุณก็จะเพิ่มขึ้นอย่างก้าวกระโดด
ลองใช้สนามฝึก SQL ที่เราแนะนำในบทความนี้เพื่อทดลองเงื่อนไขต่างๆ ดูนะครับ SQL นั้น ยิ่งเขียนมาก ยิ่งลองมาก ก็ยิ่งเก่งขึ้น หวังว่าบทความนี้จะเป็นส่วนหนึ่งที่ช่วยให้คุณเดินทางสู่การเป็นเจ้าแห่ง SQL ได้นะครับ!