0Pricing
SQL Academy · درس

المسافة وأقرب الجيران

اعثر على ما هو قريب

المسافة وأقرب الجيران درس مجاني في SQL Academy على CoddyKit. هذا هو الدرس 2 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في SQL Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة SQL Academy 4 دروس في المجموع.

ما المقصود بالمسافة المكانية؟

في قواعد البيانات الجغرافية المكانية، تشير المسافة إلى الفاصل المقاس بين موقعين جغرافيين. ويوفر PostGIS دوالًا قوية لحساب المسافات بين النقاط والخطوط والمضلعات وسائر أنواع geometry.

يتيح لكم فهم استعلامات المسافة الإجابة عن أسئلة مثل: ما المطعم الأقرب إليّ؟ أو أي العملاء يبعدون مسافة لا تتجاوز 5 كم عن مستودعنا؟

الدالة ST_Distance

تُرجع ST_Distance(geom_a, geom_b) الحد الأدنى للمسافة بين كائنين هندسيين. وبشكل افتراضي، عند استخدام أنواع geometry العادية، تكون النتيجة بوحدات نظام الإحداثيات المرجعي نفسه (وعادةً ما تكون بالدرجات بالنسبة إلى EPSG:4326).

للحصول على نتائج مفيدة بالمتر، ينبغي استخدام أنواع geography أو إعادة إسقاط بياناتكم.

SELECT ST_Distance(
  ST_MakePoint(28.9784, 41.0082)::geography,
  ST_MakePoint(29.0100, 41.0200)::geography
) AS distance_meters;

إعداد جدول نموذجي

لننشئ جدولًا بسيطًا للأماكن مزودًا بإحداثيات جغرافية. سنستخدم نوع geography بحيث تُرجع جميع حسابات المسافة قيمًا بالمتر تلقائيًا، من دون الحاجة إلى إسقاط يدوي.

سيحتوي هذا الجدول على مقاهٍ في مدينة، لكل منها اسم وموقع مخزن كنقطة.

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).

تكون النتيجة بالمتر لأننا استخدمنا نوع geography.

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;

العامل &lt;-&gt; للجار الأقرب

يوفر PostGIS العامل <-> (KNN — K Nearest Neighbors) الذي يستفيد من الفهرس. وعلى عكس 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 عندما تقع هندستان ضمن مسافة محددة من إحداهما إلى الأخرى. وبالنسبة إلى أنواع geography، تكون المسافة بالمتر.

وهذا أكثر كفاءة من 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 المسافة الدقيقة بين هندستين؛ استخدموا نوع geography للحصول على النتائج بالمتر تلقائيًا.
  • تصفّي ST_DWithin الصفوف التي تقع ضمن نصف قطر بكفاءة باستخدام الفهرس المكاني — ففضّلوها على ST_Distance < radius في عبارات WHERE.
  • يستفيد <-> operator (KNN) في ORDER BY من الفهرس، وهو أسرع طريقة لاسترداد أقرب N من الجيران.
  • اجمعوا بين ST_DWithin كمرشح أولي وترتيب <-> للحصول على استعلامات أفضل N نتائج ضمن نصف القطر بأعلى كفاءة.
  • يتيح لكم CROSS JOIN LATERAL العثور على أقرب تطابق من جدول آخر لكل صف على حدة.
  • يمكن لدوال النوافذ مثل ROW_NUMBER() تعيين ترتيب حسب القرب للنتائج المرتبة وفق المسافة.

تشكل هذه الأنماط أساس الميزات المعتمدة على الموقع في التطبيقات الواقعية.

الأسئلة الشائعة

هل درس «المسافة وأقرب الجيران» مجاني؟

نعم — نص درس «المسافة وأقرب الجيران» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة SQL Academy، انتقل إلى CoddyKit PRO. تتضمن دورة SQL Academy 4 دروس في المجموع.

ماذا ستتعلم في «المسافة وأقرب الجيران»؟

اعثر على ما هو قريب تتمرن على SQL Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.

هل أحتاج إلى خبرة سابقة لأبدأ SQL Academy؟

لا تُشترط خبرة سابقة. SQL Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 2 من أصل 4.

كم من الوقت يستغرق درس «المسافة وأقرب الجيران»؟

معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.

هل يمكنني كتابة وتشغيل أكواد في درس SQL Academy هذا؟

نعم. كل درس في SQL Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.

جميع الدروس في هذه الدورة

  1. أنواع البيانات المكانية
  2. المسافة وأقرب الجيران
  3. الربط المكاني والاحتواء
  4. الفهارس المكانية (GiST)
← العودة إلى SQL Academy