ระยะทางและเพื่อนบ้านที่ใกล้ที่สุด
ค้นหาสิ่งที่อยู่ใกล้เคียง
ระยะทางและเพื่อนบ้านที่ใกล้ที่สุด เป็นบทเรียน SQL Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน SQL Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส SQL Academy มีบทเรียนทั้งหมด 4 บทเรียน
ระยะทางเชิงพื้นที่คืออะไร
ในฐานข้อมูลภูมิสารสนเทศ ระยะทาง คือระยะห่างที่วัดได้ระหว่างตำแหน่งทางภูมิศาสตร์สองตำแหน่ง PostGIS มีฟังก์ชันอันทรงพลังสำหรับคำนวณระยะทางระหว่างจุด เส้น รูปหลายเหลี่ยม และชนิดข้อมูลเรขาคณิตอื่น ๆ
ความเข้าใจเกี่ยวกับคำค้นระยะทางช่วยให้คุณตอบคำถามต่าง ๆ ได้ เช่น ร้านอาหารที่อยู่ใกล้ฉันที่สุดอยู่ที่ไหน หรือ ลูกค้ารายใดอยู่ห่างจากคลังสินค้าของเราไม่เกิน 5 กิโลเมตร
ฟังก์ชัน ST_Distance
ST_Distance(geom_a, geom_b) คืนค่าระยะทางต่ำสุดระหว่างวัตถุเรขาคณิตสองรายการ โดยค่าเริ่มต้น เมื่อใช้ชนิดข้อมูลเรขาคณิตทั่วไป ผลลัพธ์จะมีหน่วยเดียวกับระบบอ้างอิงพิกัด ซึ่งโดยปกติสำหรับ EPSG:4326 จะเป็นองศา
หากต้องการผลลัพธ์ที่มีความหมายเป็นเมตร ควรใช้ชนิดข้อมูล ภูมิศาสตร์ หรือแปลงข้อมูลไปยังระบบพิกัดอื่น
SELECT ST_Distance(
ST_MakePoint(28.9784, 41.0082)::geography,
ST_MakePoint(29.0100, 41.0200)::geography
) AS distance_meters;การตั้งค่าตารางตัวอย่าง
เราจะสร้างตารางอย่างง่ายสำหรับเก็บสถานที่พร้อมพิกัดทางภูมิศาสตร์ โดยใช้ชนิดข้อมูล ภูมิศาสตร์ เพื่อให้การคำนวณระยะทางทั้งหมดคืนค่าเป็นเมตรโดยอัตโนมัติ ไม่ต้องแปลงระบบพิกัดด้วยตนเอง
ตารางนี้จะเก็บข้อมูลคาเฟ่ในเมือง โดยแต่ละรายการมีชื่อและตำแหน่งที่จัดเก็บเป็นจุด
CREATE TABLE cafes (
id SERIAL PRIMARY KEY,
name TEXT NOT NULL,
location GEOGRAPHY(Point, 4326)
);
INSERT INTO cafes (name, location) VALUES
('Cafe Alpha', ST_MakePoint(28.9784, 41.0082)::geography),
('Cafe Beta', ST_MakePoint(28.9900, 41.0150)::geography),
('Cafe Gamma', ST_MakePoint(29.0100, 41.0200)::geography),
('Cafe Delta', ST_MakePoint(28.9650, 40.9980)::geography),
('Cafe Epsilon', ST_MakePoint(29.0250, 41.0350)::geography);การค้นหาระยะทางจากจุดคงที่
เมื่อมีข้อมูลตำแหน่งแล้ว คุณสามารถคำนวณระยะทางจากทุกแถวไปยังจุดอ้างอิงได้ ในที่นี้เราจะคำนวณว่าคาเฟ่แต่ละแห่งอยู่ห่างจากผู้ใช้ที่ยืนอยู่ ณ พิกัด (28.9800, 41.0100) เท่าใด
ผลลัพธ์เป็นเมตร เพราะเราใช้ชนิดข้อมูลภูมิศาสตร์
SELECT
name,
ROUND(
ST_Distance(
location,
ST_MakePoint(28.9800, 41.0100)::geography
)::NUMERIC
) AS distance_m
FROM cafes
ORDER BY distance_m;การค้นหาเพื่อนบ้านที่ใกล้ที่สุด
หากต้องการค้นหาตำแหน่งเดียวที่ใกล้ที่สุดจากจุดที่กำหนด ให้เรียงตามระยะทางแล้วเลือกเพียงหนึ่งแถวด้วย LIMIT 1 นี่คือคำค้นหาเพื่อนบ้านที่ใกล้ที่สุดแบบมาตรฐาน
รูปแบบนี้พบได้บ่อยมากในแอปพลิเคชันที่ใช้ข้อมูลตำแหน่ง เช่น การค้นหาร้านค้า แพทย์ หรือป้ายขนส่งสาธารณะที่ใกล้ที่สุด
SELECT
name,
ROUND(
ST_Distance(
location,
ST_MakePoint(28.9800, 41.0100)::geography
)::NUMERIC
) AS distance_m
FROM cafes
ORDER BY location <-> ST_MakePoint(28.9800, 41.0100)::geography
LIMIT 1;ตัวดำเนินการ <-> สำหรับค้นหาเพื่อนบ้านที่ใกล้ที่สุด
PostGIS มีตัวดำเนินการ <-> (KNN — เพื่อนบ้านที่ใกล้ที่สุด K ราย) ซึ่งรองรับการใช้ดัชนี ต่างจาก ST_Distance ในส่วนคำสั่ง ORDER BY ตรงที่ <-> สามารถใช้ดัชนีเชิงพื้นที่ GiSTเพื่อหลีกเลี่ยงการสแกนทุกแถวได้
เมื่อจำเป็นต้องค้นหาเพื่อนบ้านที่ใกล้ที่สุดอย่างมีประสิทธิภาพ ควรเลือกใช้ <-> ใน ORDER BY เสมอ สร้างดัชนีเพื่อรองรับการทำงานดังนี้:
CREATE INDEX ON cafes USING GIST (location);
SELECT
name,
ROUND(
ST_Distance(
location,
ST_MakePoint(28.9800, 41.0100)::geography
)::NUMERIC
) AS distance_m
FROM cafes
ORDER BY location <-> ST_MakePoint(28.9800, 41.0100)::geography
LIMIT 5;การกรองตามระยะทาง (ST_DWithin)
ST_DWithin(geom_a, geom_b, distance) คืนค่า TRUE เมื่อข้อมูลเรขาคณิตสองรายการอยู่ห่างกันไม่เกินระยะที่กำหนด สำหรับชนิดข้อมูลภูมิศาสตร์ ระยะทางมีหน่วยเป็นเมตร
วิธีนี้มีประสิทธิภาพมากกว่า ST_Distance(...) < radius ในส่วนคำสั่ง WHERE เพราะ ST_DWithin รองรับการใช้ดัชนีและจะหยุดค้นหาทันทีที่ตรงตามเงื่อนไข
SELECT
name,
ROUND(
ST_Distance(
location,
ST_MakePoint(28.9800, 41.0100)::geography
)::NUMERIC
) AS distance_m
FROM cafes
WHERE ST_DWithin(
location,
ST_MakePoint(28.9800, 41.0100)::geography,
2000
)
ORDER BY distance_m;รายการ N อันดับแรกที่ใกล้ที่สุดพร้อมตัวกรองรัศมี
รูปแบบที่ใช้บ่อยในระบบจริงคือการใช้ ST_DWithin เป็นตัวกรองเบื้องต้นร่วมกับการเรียงลำดับด้วย <-> การตรวจสอบด้วย ST_DWithin ใช้ดัชนีเชิงพื้นที่เพื่อคัดแถวที่อยู่ไกลออกอย่างรวดเร็ว จากนั้นจึงเรียงผู้สมัครที่เหลือตามระยะทางจริง
วิธีนี้ช่วยให้คุณค้นหาตำแหน่ง N แห่งที่ใกล้ที่สุดภายในรัศมีสูงสุดได้อย่างมีประสิทธิภาพมาก
SELECT
name,
ROUND(
ST_Distance(
location,
ST_MakePoint(28.9800, 41.0100)::geography
)::NUMERIC
) AS distance_m
FROM cafes
WHERE ST_DWithin(
location,
ST_MakePoint(28.9800, 41.0100)::geography,
5000
)
ORDER BY location <-> ST_MakePoint(28.9800, 41.0100)::geography
LIMIT 3;ระยะทางระหว่างสองตาราง (ระยะทางข้าม)
คุณสามารถคำนวณระยะทางระหว่างแถวในสองตารางที่แตกต่างกันได้โดยใช้ JOIN ร่วมกับ ST_Distance วิธีนี้มีประโยชน์สำหรับการจับคู่ เช่น จับคู่ลูกค้าแต่ละรายกับคลังสินค้าที่ใกล้ที่สุด หรือจับคู่เหตุการณ์แต่ละรายการกับโรงพยาบาลที่ใกล้ที่สุด
ด้านล่างนี้ เราจะค้นหาคาเฟ่ที่ใกล้ที่สุดสำหรับผู้ใช้แต่ละรายในตาราง users โดยใช้การเชื่อมตารางแบบด้านข้าง ซึ่งเป็นรูปแบบของ PostgreSQL ที่ทรงพลังสำหรับคำค้นย่อยแยกตามแต่ละแถว
SELECT
u.username,
c.name AS nearest_cafe,
ROUND(ST_Distance(u.location, c.location)::NUMERIC) AS distance_m
FROM (
VALUES
('alice', ST_MakePoint(28.9810, 41.0095)::geography),
('bob', ST_MakePoint(29.0200, 41.0300)::geography)
) AS u(username, location)
CROSS JOIN LATERAL (
SELECT name, location
FROM cafes
ORDER BY location <-> u.location
LIMIT 1
) c;การจัดรูปแบบผลลัพธ์ระยะทาง
ค่าระยะทางดิบที่เป็นเมตรอาจอ่านได้ยาก คุณสามารถจัดรูปแบบเป็นกิโลเมตรหรือเพิ่มป้ายกำกับที่อ่านเข้าใจง่ายได้โดยใช้ส่วนแสดงผล CASE และการจัดรูปแบบข้อความ ต่อไปนี้คือตัวอย่างคำค้นที่แสดงระยะทางเป็นเมตรสำหรับระยะสั้น และเป็นกิโลเมตรสำหรับระยะที่ไกลขึ้น
SELECT
name,
CASE
WHEN ST_Distance(location, ST_MakePoint(28.9800, 41.0100)::geography) < 1000
THEN ROUND(ST_Distance(location, ST_MakePoint(28.9800, 41.0100)::geography)::NUMERIC)
|| ' m'
ELSE ROUND((ST_Distance(location, ST_MakePoint(28.9800, 41.0100)::geography) / 1000.0)::NUMERIC, 2)
|| ' km'
END AS formatted_distance
FROM cafes
ORDER BY location <-> ST_MakePoint(28.9800, 41.0100)::geography;การกำหนดอันดับตามระยะทาง
ฟังก์ชันหน้าต่างอย่าง RANK() และ ROW_NUMBER() ทำงานร่วมกับคำค้นระยะทางได้อย่างเหมาะเจาะ คุณสามารถกำหนดอันดับตามความใกล้ให้กับตำแหน่งแต่ละแห่งเมื่อเทียบกับผู้ใช้ ซึ่งมีประโยชน์สำหรับสร้างรายการคำแนะนำหรือผลการค้นหาที่เรียงตามความใกล้
SELECT
name,
ROUND(
ST_Distance(
location,
ST_MakePoint(28.9800, 41.0100)::geography
)::NUMERIC
) AS distance_m,
ROW_NUMBER() OVER (
ORDER BY location <-> ST_MakePoint(28.9800, 41.0100)::geography
) AS proximity_rank
FROM cafes;ตรวจสอบความรู้
ทดสอบความเข้าใจเกี่ยวกับคำค้นระยะทางและการค้นหาเพื่อนบ้านที่ใกล้ที่สุดใน PostGIS
ทบทวนบทเรียน
ในบทเรียนนี้ คุณได้เรียนรู้วิธีทำงานกับระยะทางเชิงพื้นที่และคำค้นหาเพื่อนบ้านที่ใกล้ที่สุดใน PostGIS:
- ST_Distance คำนวณระยะทางที่แม่นยำระหว่างข้อมูลเรขาคณิตสองรายการ ใช้ชนิดข้อมูล ภูมิศาสตร์ เพื่อให้ได้หน่วยเป็นเมตรโดยอัตโนมัติ
- ST_DWithin กรองแถวที่อยู่ภายในรัศมีได้อย่างมีประสิทธิภาพโดยใช้ดัชนีเชิงพื้นที่ ควรเลือกใช้แทน
ST_Distance < radiusในส่วนคำสั่ง WHERE - ตัวดำเนินการ <-> (KNN) ใน ORDER BY รองรับการใช้ดัชนี และเป็นวิธีที่รวดเร็วที่สุดในการดึงเพื่อนบ้านที่ใกล้ที่สุดจำนวน N รายการ
- ใช้
ST_DWithinเป็นตัวกรองเบื้องต้นร่วมกับการเรียงลำดับด้วย<->เพื่อให้คำค้นหา N อันดับแรกภายในรัศมีมีประสิทธิภาพสูงสุด - CROSS JOIN LATERAL ช่วยให้คุณค้นหารายการที่ตรงกันจากอีกตารางหนึ่งแยกตามแต่ละแถวได้
- ฟังก์ชันหน้าต่างอย่าง
ROW_NUMBER()สามารถกำหนดอันดับตามความใกล้ให้กับผลลัพธ์ที่เรียงตามระยะทางได้
รูปแบบเหล่านี้เป็นรากฐานสำคัญของฟีเจอร์ที่ใช้ข้อมูลตำแหน่งในแอปพลิเคชันจริง
คำถามที่พบบ่อย
บทเรียน “ระยะทางและเพื่อนบ้านที่ใกล้ที่สุด” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “ระยะทางและเพื่อนบ้านที่ใกล้ที่สุด” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส SQL Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส SQL Academy มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “ระยะทางและเพื่อนบ้านที่ใกล้ที่สุด”
ค้นหาสิ่งที่อยู่ใกล้เคียง คุณปฏิบัติ SQL Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน SQL Academy หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน SQL Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน
บทเรียน “ระยะทางและเพื่อนบ้านที่ใกล้ที่สุด” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน SQL Academy นี้ได้ไหม
ได้ บทเรียน SQL Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- ชนิดข้อมูลเชิงพื้นที่
- ระยะทางและเพื่อนบ้านที่ใกล้ที่สุด
- การเชื่อมตารางเชิงพื้นที่และการตรวจสอบการครอบคลุม
- ดัชนีเชิงพื้นที่ (GiST)