【คำสั่ง BETWEEN ใน SQL】ฝึกฝนการค้นหาตามช่วง! วิธีระบุช่วงของตัวเลขและวันที่อย่างชาญฉลาด
ในการพัฒนาเว็บไซต์และแอปพลิเคชัน มีหลายกรณีที่คุณต้องการดึงข้อมูลที่อยู่ในช่วงที่กำหนด เช่น "สินค้าที่มีราคาตั้งแต่ 1,000 บาท ถึง 5,000 บาท" หรือ "ผู้ใช้ที่ลงทะเบียนระหว่างวันที่ 1 ถึง 30 มิถุนายน"
เมื่อต้องเขียนเงื่อนไขเช่นนี้ใน WHERE clause คุณจะทำอย่างไร?
WHERE price >= 1000 AND price <= 5000
แน่นอนว่าคุณสามารถระบุช่วงได้โดยใช้ตัวดำเนินการเปรียบเทียบ (>=, <=) และ AND เช่นนี้ แต่ SQL ได้เตรียมคำสั่งพิเศษไว้เพื่อให้ "การค้นหาตามช่วง" นี้ดูเป็นธรรมชาติและกระชับยิ่งขึ้น นั่นคือพระเอกของเราในวันนี้ BETWEEN clause
ในบทความนี้ เราจะอธิบายอย่างละเอียดตั้งแต่การใช้ BETWEEN clause พื้นฐาน การประยุกต์ใช้กับช่วงวันที่ และรูปแบบปฏิเสธ NOT BETWEEN พร้อมด้วยโค้ดที่สามารถคัดลอกไปใช้ได้ทันที มาเลิกเขียนโค้ดที่ยืดยาวด้วยตัวดำเนินการเปรียบเทียบ แล้วมาฝึกฝนทักษะการเขียน SQL ที่ชาญฉลาดและเข้าใจง่ายสำหรับทุกคนกันเถอะ!
การเตรียมตัว: มาเตรียมข้อมูลคำสั่งซื้อสำหรับค้นหากัน
เพื่อทดลองการค้นหาตามช่วง เราต้องมีข้อมูลสำหรับใช้เป็นเป้าหมายกันก่อน ครั้งนี้ เราจะสร้างตาราง orders ที่จำลองประวัติการสั่งซื้อของเว็บไซต์ E-commerce การมีข้อมูลราคาและวันที่สั่งซื้อที่หลากหลายจะช่วยให้เราเห็นผลของ BETWEEN clause ได้ง่ายขึ้น
-- ถ้ามีตาราง orders อยู่แล้วให้ลบออก (เพื่อให้สามารถทดสอบซ้ำได้)
DROP TABLE IF EXISTS orders;
-- สร้างตาราง orders ใหม่
CREATE TABLE orders (
id INTEGER PRIMARY KEY,
product_name TEXT NOT NULL,
price INTEGER NOT NULL,
order_date DATE NOT NULL,
quantity INTEGER NOT NULL
);
-- ใส่ข้อมูลเริ่มต้น
INSERT INTO orders (id, product_name, price, order_date, quantity) VALUES
(1, 'ปากกาสุดเจ๋ง', 200, '2025-06-05', 3),
(2, 'สมุดโน้ตเวทมนตร์', 500, '2025-06-10', 5),
(3, 'หม้อหุงข้าวขั้นเทพ', 30000, '2025-06-15', 1),
(4, 'แอปเปิ้ลมหัศจรรย์', 980, '2025-06-20', 10),
(5, 'ฮับ USB-C', 4500, '2025-06-25', 2),
(6, 'พู่กันโบราณ', 12000, '2025-06-30', 1),
(7, 'ช็อกโกแลตพรีเมียม', 3500, '2025-07-01', 4);
ตอนนี้เราพร้อมที่จะดึงข้อมูลโดยระบุช่วงต่างๆ แล้ว
【พื้นฐาน】การระบุช่วงของตัวเลขด้วย BETWEEN Clause
ไวยากรณ์พื้นฐานของ BETWEEN clause นั้นชัดเจนมาก
WHERE ชื่อคอลัมน์ BETWEEN ค่าต่ำสุด AND ค่าสูงสุด;
จุดที่สำคัญที่สุดตรงนี้คือ ช่วงของ BETWEEN clause จะรวมค่าต่ำสุดและค่าสูงสุดที่ระบุไว้ด้วย (เป็นแบบ >= และ <=) นั่นหมายความว่า WHERE price BETWEEN 1000 AND 5000 มีความหมายเหมือนกับ WHERE price >= 1000 AND price <= 5000 ทุกประการ ให้จำจุดนี้ "รวมขอบเขตทั้งสองข้าง" ไว้ให้ดีนะครับ
สถานการณ์: "ค้นหาสินค้าทั้งหมดที่มีราคาอยู่ระหว่าง 1,000 ถึง 5,000 บาท"
SELECT * FROM orders
WHERE price BETWEEN 1000 AND 5000;
ผลลัพธ์:
id | product_name | price | order_date | quantity
---|-------------------|-------|------------|----------
5 | ฮับ USB-C | 4500 | 2025-06-25 | 2
7 | ช็อกโกแลตพรีเมียม | 3500 | 2025-07-01 | 4
โค้ดดูสะอาดตากว่าการใช้ตัวดำเนินการเปรียบเทียบสองตัว และสื่อถึงเจตนา "ช่วงราคา 1,000 ถึง 5,000" ได้ตรงไปตรงมามากกว่าใช่ไหมครับ
【การประยุกต์ใช้】การระบุช่วงของวันที่ด้วย BETWEEN Clause
ข้อดีของ BETWEEN clause คือไม่เพียงแต่ใช้กับตัวเลขได้ แต่ยังสามารถใช้กับการระบุช่วงของวันที่ (DATE type) และวันเวลา (DATETIME type) ได้อีกด้วย ในเว็บแอปพลิเคชันมีความต้องการดึงข้อมูลในช่วงเวลาที่กำหนดบ่อยมาก นี่จึงเป็นเทคนิคที่ใช้กันแพร่หลาย
สถานการณ์: "ค้นหาคำสั่งซื้อทั้งหมดที่เกิดขึ้นในเดือนมิถุนายน 2025"
ในกรณีนี้ เราจะระบุช่วงเริ่มต้นเป็น "2025-06-01" และช่วงสิ้นสุดเป็น "2025-06-30"
SELECT * FROM orders
WHERE order_date BETWEEN '2025-06-01' AND '2025-06-30';
ผลลัพธ์:
id | product_name | price | order_date | quantity
---|---------------------|-------|------------|----------
1 | ปากกาสุดเจ๋ง | 200 | 2025-06-05 | 3
2 | สมุดโน้ตเวทมนตร์ | 500 | 2025-06-10 | 5
3 | หม้อหุงข้าวขั้นเทพ | 30000 | 2025-06-15 | 1
4 | แอปเปิ้ลมหัศจรรย์ | 980 | 2025-06-20 | 10
5 | ฮับ USB-C | 4500 | 2025-06-25 | 2
6 | พู่กันโบราณ | 12000 | 2025-06-30 | 1
อย่างที่คุณเห็น คำสั่งซื้อในวันที่ 1 และ 30 มิถุนายนก็ถูกรวมอยู่ในผลลัพธ์ด้วย ซึ่งก็เป็นผลมาจากคุณสมบัติ "รวมขอบเขตทั้งสองข้าง" ของ BETWEEN clause นั่นเอง
【เงื่อนไขตรงกันข้าม】การระบุสิ่งที่อยู่นอกช่วงด้วย NOT BETWEEN
หากคุณต้องการค้นหาสิ่งที่อยู่ **นอก** ช่วงที่กำหนด ให้ใช้ NOT BETWEEN clause
มีข้อควรระวังหนึ่งข้อที่นี่ ขณะที่ price BETWEEN 1000 AND 5000 หมายถึง "มากกว่าหรือเท่ากับ 1000 และน้อยกว่าหรือเท่ากับ 5000", price NOT BETWEEN 1000 AND 5000 จะหมายถึง "น้อยกว่า 1000 **หรือ** มากกว่า 5000" (price < 1000 OR price > 5000) นั่นคือค่าที่ขอบเขตจะไม่ถูกรวมอยู่ในผลลัพธ์
สถานการณ์: "ค้นหาสินค้าทั้งหมดที่ราคาถูกมาก (น้อยกว่า 1,000) หรือแพงมาก (มากกว่า 5,000)"
SELECT * FROM orders
WHERE price NOT BETWEEN 1000 AND 5000;
ผลลัพธ์:
id | product_name | price | order_date | quantity
---|---------------------|-------|------------|----------
1 | ปากกาสุดเจ๋ง | 200 | 2025-06-05 | 3
2 | สมุดโน้ตเวทมนตร์ | 500 | 2025-06-10 | 5
3 | หม้อหุงข้าวขั้นเทพ | 30000 | 2025-06-15 | 1
4 | แอปเปิ้ลมหัศจรรย์ | 980 | 2025-06-20 | 10
6 | พู่กันโบราณ | 12000 | 2025-06-30 | 1
แม้ว่าข้อมูลตัวอย่างของเราจะไม่มีสินค้าที่ราคา 1,000 และ 5,000 พอดี แต่โปรดจำไว้ว่าถึงแม้จะมี ก็จะไม่ถูกรวมอยู่ในผลลัพธ์นี้
【สนามเด็กเล่นแบบโต้ตอบ】มาฝึกฝนการค้นหาตามช่วงในเบราว์เซอร์ของคุณ!
ถึงเวลาเปลี่ยนความรู้ให้เป็นทักษะแล้ว! คัดลอกโค้ด HTML ทั้งหมดด้านล่าง, บันทึกเป็นไฟล์ชื่อ sql_between_test.html, และเปิดในเบราว์เซอร์ของคุณ สภาพแวดล้อม SQL ส่วนตัวของคุณจะเปิดขึ้นมา พร้อมกับตาราง orders ที่เราใช้ในบทความนี้
ลองเปลี่ยนช่วงของตัวเลขหรือวันที่ดู เพื่อให้เข้าใจถึงความรู้สึก "รวมขอบเขตทั้งสองข้าง" ของ BETWEEN clause และลองใช้ NOT BETWEEN เพื่อดูว่าผลลัพธ์จะเปลี่ยนแปลงไปอย่างไร!
<!DOCTYPE html>
<html lang="th">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>สนามเด็กเล่นออนไลน์สำหรับ SQL BETWEEN Clause</title>
<style>
body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; line-height: 1.7; color: #333; max-width: 800px; margin: 2rem auto; padding: 0 1rem; }
h1 { color: #16a085; }
textarea { width: 100%; height: 180px; font-family: "SF Mono", "Consolas", monospace; font-size: 16px; padding: 12px; border: 1px solid #ccc; border-radius: 6px; box-sizing: border-box; margin-bottom: 1rem; }
button { background-color: #1abc9c; color: white; border: none; padding: 12px 22px; font-size: 16px; border-radius: 6px; cursor: pointer; transition: background-color 0.2s; }
button:hover { background-color: #16a085; }
button:disabled { background-color: #bdc3c7; cursor: not-allowed; }
#result-container { margin-top: 2rem; border: 1px solid #ddd; padding: 1rem; border-radius: 6px; background: #fdfdfd; min-height: 50px; }
#error-message { color: #e74c3c; font-weight: bold; }
table { border-collapse: collapse; width: 100%; margin-top: 1rem; }
th, td { border: 1px solid #ddd; padding: 10px; text-align: left; }
th { background-color: #f2f2f2; }
tr:nth-child(even) { background-color: #f9f9f9; }
</style>
<script src="https://cdnjs.cloudflare.com/ajax/libs/sql.js/1.10.3/sql-wasm.js"></script>
</head>
<body>
<h1>มาลองใช้ SQL กัน!</h1>
<p>ป้อนคำสั่ง SQL ในช่องข้อความด้านล่างแล้วคลิกปุ่ม "ประมวลผล" ลองใช้ช่วงต่างๆ ดูสิ!</p>
<textarea id="sql-input">-- ค้นหาคำสั่งซื้อที่เกิดขึ้นระหว่างวันที่ 10 ถึง 25 มิถุนายน
SELECT * FROM orders
WHERE order_date BETWEEN '2025-06-10' AND '2025-06-25';
</textarea>
<button id="execute-btn">ประมวลผล</button>
<div id="result-container">
<p id="error-message"></p>
<div id="result-output"></div>
</div>
<script>
const sqlInput = document.getElementById('sql-input');
const executeBtn = document.getElementById('execute-btn');
const errorMsg = document.getElementById('error-message');
const resultOutput = document.getElementById('result-output');
let db;
async function initDb() {
executeBtn.disabled = true;
executeBtn.textContent = 'กำลังเตรียมฐานข้อมูล...';
try {
const SQL = await initSqlJs({
locateFile: file => `https://cdnjs.cloudflare.com/ajax/libs/sql.js/1.10.3/${file}`
});
db = new SQL.Database();
const setupSql = `
DROP TABLE IF EXISTS orders;
CREATE TABLE orders (id INTEGER PRIMARY KEY, product_name TEXT NOT NULL, price INTEGER NOT NULL, order_date DATE NOT NULL, quantity INTEGER NOT NULL);
INSERT INTO orders (id, product_name, price, order_date, quantity) VALUES
(1, 'ปากกาสุดเจ๋ง', 200, '2025-06-05', 3),
(2, 'สมุดโน้ตเวทมนตร์', 500, '2025-06-10', 5),
(3, 'หม้อหุงข้าวขั้นเทพ', 30000, '2025-06-15', 1),
(4, 'แอปเปิ้ลมหัศจรรย์', 980, '2025-06-20', 10),
(5, 'ฮับ USB-C', 4500, '2025-06-25', 2),
(6, 'พู่กันโบราณ', 12000, '2025-06-30', 1),
(7, 'ช็อกโกแลตพรีเมียม', 3500, '2025-07-01', 4);
`;
db.run(setupSql);
executeBtn.disabled = false;
executeBtn.textContent = 'ประมวลผล';
resultOutput.innerHTML = '<p>พร้อมแล้ว! คุณสามารถทดลองใช้คำสั่ง SQL ของคุณเองได้เลย</p>';
} catch (err) {
errorMsg.textContent = 'การเริ่มต้นฐานข้อมูลล้มเหลว: ' + err.message;
console.error(err);
}
}
function executeSql() {
if (!db) return;
const sql = sqlInput.value;
errorMsg.textContent = '';
resultOutput.innerHTML = '';
try {
const results = db.exec(sql);
if (results.length === 0) {
resultOutput.innerHTML = '<p>คำสั่งสำเร็จ แต่ไม่มีผลลัพธ์ส่งกลับมา</p>';
return;
}
results.forEach(result => {
const table = document.createElement('table');
const thead = document.createElement('thead');
const tbody = document.createElement('tbody');
const headerRow = document.createElement('tr');
result.columns.forEach(colName => {
const th = document.createElement('th');
th.textContent = colName;
headerRow.appendChild(th);
});
thead.appendChild(headerRow);
result.values.forEach(row => {
const bodyRow = document.createElement('tr');
row.forEach(cellValue => {
const td = document.createElement('td');
td.textContent = cellValue === null ? 'NULL' : cellValue;
bodyRow.appendChild(td);
});
tbody.appendChild(bodyRow);
});
table.appendChild(thead);
table.appendChild(tbody);
resultOutput.appendChild(table);
});
} catch (err) {
errorMsg.textContent = 'เกิดข้อผิดพลาด SQL: ' + err.message;
console.error(err);
}
}
executeBtn.addEventListener('click', executeSql);
initDb();
</script>
</body>
</html>
ข้อควรระวัง: การจัดการวันเวลาและลำดับของค่า
แม้ว่า BETWEEN clause จะเรียบง่ายและทรงพลัง แต่ก็มีข้อควรระวังบางประการ
- ลำดับของค่า: เมื่อคุณเขียน
BETWEEN A AND Bคุณต้องระบุค่าที่น้อยกว่าสำหรับ A และค่าที่มากกว่าสำหรับ B เสมอ หากคุณสลับลำดับ เช่นBETWEEN 5000 AND 1000มันจะไม่พบระเบียนใดเลย แม้ว่าจะมีข้อมูลอยู่ในช่วงนั้นก็ตาม ควรเขียนในลำดับ "ค่าต่ำสุด AND ค่าสูงสุด" เสมอ - การจัดการวันเวลา (ประเภท TIMESTAMP เป็นต้น): คุณต้องระมัดระวังเป็นพิเศษเมื่อใช้
BETWEENกับคอลัมน์ที่มีเวลาด้วย (เช่น `YYYY-MM-DD HH:MM:SS`) ตัวอย่างเช่น หากคุณระบุว่าorder_datetime BETWEEN '2025-06-01' AND '2025-06-30'สิ่งนี้จะถูกตีความภายในว่าถึง `'2025-06-30 00:00:00'` เท่านั้น ดังนั้น คำสั่งซื้อที่ทำในบ่ายวันที่ 30 มิถุนายน (เช่น '2025-06-30 15:00:00') จะอยู่นอกช่วงและไม่ถูกรวมอยู่ในผลลัพธ์ หากคุณต้องการรวมทั้งวันของวันที่ 30 มิถุนายน วิธีที่เชื่อถือได้คือการระบุเวลาอย่างชัดเจน เช่นBETWEEN '2025-06-01 00:00:00' AND '2025-06-30 23:59:59'หรือใช้ตัวดำเนินการเปรียบเทียบเพื่อระบุว่า "ก่อนเริ่มต้นวันถัดไป" เช่นorder_datetime >= '2025-06-01' AND order_datetime < '2025-07-01'
สรุป
ในบทความนี้ เราได้เรียนรู้เกี่ยวกับ BETWEEN clause ซึ่งช่วยให้สามารถเขียนการค้นหาตามช่วงของตัวเลขและวันที่ได้อย่างเป็นธรรมชาติ
- ไวยากรณ์พื้นฐาน:
WHERE ชื่อคอลัมน์ BETWEEN ค่าต่ำสุด AND ค่าสูงสุดซึ่งอ่านง่ายกว่าการใช้ตัวดำเนินการเปรียบเทียบ (>= ... AND <= ...) - ช่วงจะรวมขอบเขตทั้งสองข้าง: นี่คือจุดที่สำคัญที่สุด
BETWEENclause จะประเมินผลเป็น "มากกว่าหรือเท่ากับ และ น้อยกว่าหรือเท่ากับ" - `NOT BETWEEN`: ดึงข้อมูลที่อยู่นอกช่วง ซึ่งจะประเมินผลเป็น "น้อยกว่า หรือ มากกว่า" และไม่รวมค่าที่ขอบเขต
- ใช้ได้กับวันที่: ด้วยการระบุสตริงในรูปแบบ
'YYYY-MM-DD'คุณสามารถทำการค้นหาตามช่วงวันที่ได้อย่างง่ายดาย - ข้อควรระวัง: ควรเขียนในลำดับ "ค่าต่ำสุด AND ค่าสูงสุด" เสมอ และต้องระวังเมื่อระบุช่วงสำหรับข้อมูลที่มีเวลา
การใช้ BETWEEN clause ได้อย่างเชี่ยวชาญจะทำให้ SQL ที่คุณเขียนนั้นเรียบง่ายและสื่อความหมายได้ชัดเจนยิ่งขึ้น ก้าวไปอีกขั้นจากการใช้ตัวดำเนินการเปรียบเทียบแบบเดิมๆ และเพิ่มเทคนิคการดึงข้อมูลที่ซับซ้อนยิ่งขึ้นลงในกล่องเครื่องมือของคุณ!