0Pricing
SQL Academy · บทเรียน

ระยะทางและเพื่อนบ้านที่ใกล้ที่สุด

ค้นหาสิ่งที่อยู่ใกล้เคียง

ระยะทางและเพื่อนบ้านที่ใกล้ที่สุด เป็นบทเรียน 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 ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. ชนิดข้อมูลเชิงพื้นที่
  2. ระยะทางและเพื่อนบ้านที่ใกล้ที่สุด
  3. การเชื่อมตารางเชิงพื้นที่และการตรวจสอบการครอบคลุม
  4. ดัชนีเชิงพื้นที่ (GiST)
← กลับไปที่ SQL Academy