الربط المكاني والاحتواء
أيّ نقاط تقع ضمن أيّ مناطق
الربط المكاني والاحتواء درس مجاني في SQL Academy على CoddyKit. هذا هو الدرس 3 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في SQL Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة SQL Academy 4 دروس في المجموع.
ما المقصود بالربط المكاني؟
يجمع الربط المكاني بين جدولين استنادًا إلى علاقة مكانية بدلًا من مفتاح مطابق. فبدلًا من السؤال «هل يساوي هذا المعرّف ذلك المعرّف؟»، نطرح أسئلة مثل «هل تقع هذه النقطة داخل ذلك المضلع؟» أو «هل يتداخل هذان الشكلان؟»
يوسّع PostGIS إمكانات PostgreSQL بإضافة أنواع هندسية ودوال مكانية تجعل عمليات الربط هذه ممكنة. وتكون النتيجة مثل نتيجة SQL JOIN العادي — صفوفًا من الجدولين مدمجة معًا — لكن شرط الربط يكون هندسيًا.
إعداد الجداول النموذجية
لننشئ جدولين للعمل معهما: cities لتخزين مواقع النقاط، وcountries لتخزين حدود المضلعات. يستخدم كلاهما النوع GEOMETRY من PostGIS مع SRID 4326 (إحداثيات خط العرض وخط الطول القياسية لنظام WGS84).
يحدد SRID (معرّف المرجع المكاني) لنظام PostGIS نظام الإحداثيات الذي ينبغي استخدامه. ويُعد SRID 4326 الأكثر شيوعًا لبيانات GPS.
CREATE TABLE countries (
id SERIAL PRIMARY KEY,
name TEXT NOT NULL,
border GEOMETRY(POLYGON, 4326)
);
CREATE TABLE cities (
id SERIAL PRIMARY KEY,
name TEXT NOT NULL,
location GEOMETRY(POINT, 4326)
);إدراج بيانات نموذجية
سنستخدم ST_GeomFromText لإدراج قيم الهندسة بتنسيق النص المعروف (WKT). وWKT هو تمثيل نصي قياسي للهندسات: POINT(lon lat) للنقاط وPOLYGON((...)) للمضلعات.
لاحظوا أن خط الطول يأتي قبل خط العرض في WKT، وهذا يتوافق مع اصطلاح X وY في الرياضيات.
INSERT INTO countries (name, border) VALUES
('France', ST_GeomFromText('POLYGON((-5 42, 8 42, 8 51, -5 51, -5 42))', 4326)),
('Spain', ST_GeomFromText('POLYGON((-9 36, 3 36, 3 44, -9 44, -9 36))', 4326));
INSERT INTO cities (name, location) VALUES
('Paris', ST_GeomFromText('POINT(2.35 48.85)', 4326)),
('Madrid', ST_GeomFromText('POINT(-3.70 40.42)', 4326)),
('Bordeaux', ST_GeomFromText('POINT(-0.58 44.84)', 4326)),
('Lisbon', ST_GeomFromText('POINT(-9.14 38.72)', 4326));ST_Contains: الدالة الأساسية
تعيد ST_Contains(geometry A, geometry B) القيمة TRUE عندما تحتوي الهندسة A الهندسة B بالكامل. وفي حالة الاستخدام لدينا، تعيد ST_Contains(country.border, city.location) القيمة true عندما تقع نقطة مدينة داخل مضلع دولة.
هذه هي جوهر عمليات الربط بالاحتواء في PostGIS. وتندرج هذه الدالة ضمن معيار OGC، وتعمل مع أي توليفة من أنواع الهندسات.
SELECT
ci.name AS city,
co.name AS country
FROM cities ci
JOIN countries co
ON ST_Contains(co.border, ci.location);ST_Within: المنظور المعاكس
إن ST_Within(geometry A, geometry B) هي العكس تمامًا من ST_Contains: فهي تعيد TRUE عندما تقع الهندسة A بالكامل داخل الهندسة B. وST_Within(city, country) مكافئة منطقيًا لـ ST_Contains(country, city).
تعطي الدالتان النتيجة نفسها هنا. والاختيار بينهما مسألة تتعلق بسهولة القراءة؛ فاختاروا الصيغة التي تبدو أكثر طبيعية في استعلامكم.
-- These two queries return identical results:
-- Using ST_Contains (country contains city)
SELECT ci.name, co.name
FROM cities ci
JOIN countries co ON ST_Contains(co.border, ci.location);
-- Using ST_Within (city is within country)
SELECT ci.name, co.name
FROM cities ci
JOIN countries co ON ST_Within(ci.location, co.border);LEFT JOIN للعثور على النقاط غير المطابقة
يستبعد JOIN العادي المدن التي لا تقع داخل أي مضلع دولة. استخدموا LEFT JOIN مع فحص WHERE ... IS NULL للعثور على النقاط التي لا تحتوي على أي مضلع يضمها، وهو أمر مفيد لاكتشاف مشكلات جودة البيانات أو النقاط الواقعة خارج نطاق التغطية.
SELECT
ci.name AS city,
co.name AS country
FROM cities ci
LEFT JOIN countries co
ON ST_Contains(co.border, ci.location)
ORDER BY co.name NULLS LAST;حساب عدد النقاط داخل كل مضلع
تظهر قوة عمليات الربط المكاني عند دمجها مع التجميع. فمن خلال ربط المدن بالدول ثم التجميع حسب الدولة، يمكنكم حساب عدد النقاط الواقعة داخل كل مضلع. ويشيع هذا النمط جدًا في التحليل الجغرافي، مثل حساب عدد المتاجر في كل منطقة، والفعاليات في كل مقاطعة، وأجهزة الاستشعار في كل نطاق، وغير ذلك.
SELECT
co.name AS country,
COUNT(ci.id) AS city_count
FROM countries co
LEFT JOIN cities ci
ON ST_Contains(co.border, ci.location)
GROUP BY co.name
ORDER BY city_count DESC;استخدام فهرس مكاني لتحسين الأداء
قد تكون عمليات الربط المكاني بطيئة في مجموعات البيانات الكبيرة، لأن كل نقطة تُختبر مقابل كل مضلع. ويتيح فهرس GIST (شجرة البحث المعممة) لـ PostGIS استخدام مرشح مسبق قائم على مربعات الإحاطة لتجاوز معظم المقارنات قبل تنفيذ اختبار ST_Contains الدقيق.
احرصوا دائمًا على إنشاء فهرس GIST لأعمدة الهندسة التي تستخدمونها في الربط أو التصفية. وسيستخدمه مخطط الاستعلام تلقائيًا.
-- Create GIST indexes on both geometry columns
CREATE INDEX idx_countries_border
ON countries USING GIST (border);
CREATE INDEX idx_cities_location
ON cities USING GIST (location);
-- The same join now benefits from index acceleration
SELECT ci.name, co.name
FROM cities ci
JOIN countries co
ON ST_Contains(co.border, ci.location);ST_Intersects: الهندسات المتداخلة
تعيد ST_Intersects(A, B) القيمة TRUE إذا اشتركت هندستان في أي نقطة، بما في ذلك مجرد التلامس عند حد فاصل. وهي أكثر تساهلًا من ST_Contains؛ إذ تتقاطع مضلعان متداخلان حتى إن لم يحتوِ أي منهما الآخر بالكامل.
في اختبارات النقطة داخل المضلع، تكون ST_Intersects وST_Contains متكافئتين، لكن ST_Intersects تستخدم فهرس GIST بكفاءة أكبر، وغالبًا ما يُفضَّل استخدامها عمليًا.
-- ST_Intersects is index-friendly and equivalent
-- to ST_Contains for point-in-polygon tests
SELECT
ci.name AS city,
co.name AS country
FROM cities ci
JOIN countries co
ON ST_Intersects(co.border, ci.location);ربط النقاط بأقرب مضلع
عندما تقع نقطة على حد فاصل تمامًا أو تكون قريبة جدًا من عدة مضلعات، قد ترغبون في اختيار أقرب مضلع بدلًا من جميع النتائج المطابقة. تقيس ST_Distance المسافة بين هندستين، مما يتيح استخدام أنماط ORDER BY + LIMIT أو الربط المتخصص LATERAL مع ORDER BY ... LIMIT 1.
يُسمى هذا ربط أقرب جار، ويشيع استخدامه عند إسناد مسارات GPS إلى مقاطع الطرق أو إسناد نقطة إلى أقرب منطقة.
-- For each city, find the single closest country centroid
SELECT DISTINCT ON (ci.name)
ci.name AS city,
co.name AS nearest_country,
ST_Distance(ci.location, ST_Centroid(co.border)) AS dist
FROM cities ci
CROSS JOIN countries co
ORDER BY ci.name, dist;مثال عملي: المطاعم في المناطق
إليكم مثالًا واقعيًا متكاملًا: تحديد منطقة المدينة التي ينتمي إليها كل مطعم، ثم حساب عدد المطاعم في كل منطقة. وينطبق هذا النمط على أي سيناريو للنقطة داخل المضلع، مثل أجهزة الصراف الآلي في الأحياء، والحوادث في الدوائر، والطلبات في مناطق التوصيل.
يستخدم الاستعلام ST_Within داخل ربط مكاني، ثم يجمع النتائج لإعداد تقرير موجز.
-- Assume tables: districts(id, name, boundary GEOMETRY)
-- restaurants(id, name, location GEOMETRY)
SELECT
d.name AS district,
COUNT(r.id) AS restaurant_count,
STRING_AGG(r.name, ', ' ORDER BY r.name) AS names
FROM districts d
LEFT JOIN restaurants r
ON ST_Within(r.location, d.boundary)
GROUP BY d.name
ORDER BY restaurant_count DESC;اختبار سريع
اختبروا مدى فهمكم لعمليات الربط المكاني والاحتواء في PostGIS.
مراجعة: عمليات الربط المكاني والاحتواء
تعلمتم في هذا الدرس كيفية الإجابة عن السؤال «ما النقاط التي تقع ضمن أي المناطق؟» باستخدام عمليات الربط المكاني في PostGIS.
أهم النقاط:
- ST_Contains(polygon, point) — تعيد true عندما يحتوي المضلع النقطة بالكامل.
- ST_Within(point, polygon) — عكسها؛ وهي مكافئة منطقيًا لـ ST_Contains.
- ST_Intersects — اختبار تداخل أكثر عمومية، وملائم للفهرسة عند اختبار النقطة داخل المضلع.
- تُعد GIST indexes على أعمدة الهندسة ضرورية لتحقيق أداء جيد على نطاق واسع.
- ادمجوا عمليات الربط المكاني مع GROUP BY لحساب النقاط أو تجميعها حسب المنطقة.
- استخدموا LEFT JOIN لاكتشاف النقاط التي تقع خارج جميع المضلعات.
تتيح عمليات الربط المكاني إجراء التحليل الجغرافي مباشرةً في SQL، من دون الحاجة إلى أداة GIS خارجية.
الأسئلة الشائعة
هل درس «الربط المكاني والاحتواء» مجاني؟
نعم — نص درس «الربط المكاني والاحتواء» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة SQL Academy، انتقل إلى CoddyKit PRO. تتضمن دورة SQL Academy 4 دروس في المجموع.
ماذا ستتعلم في «الربط المكاني والاحتواء»؟
أيّ نقاط تقع ضمن أيّ مناطق تتمرن على SQL Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.
هل أحتاج إلى خبرة سابقة لأبدأ SQL Academy؟
لا تُشترط خبرة سابقة. SQL Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 3 من أصل 4.
كم من الوقت يستغرق درس «الربط المكاني والاحتواء»؟
معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.
هل يمكنني كتابة وتشغيل أكواد في درس SQL Academy هذا؟
نعم. كل درس في SQL Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.
جميع الدروس في هذه الدورة
- أنواع البيانات المكانية
- المسافة وأقرب الجيران
- الربط المكاني والاحتواء
- الفهارس المكانية (GiST)