محتويات الدورة

PostgreSQL / الأساسي: الأسس العلاقية / الدرس 4

الربط وتعددية العلاقات

اجمع العملاء والحجوزات والدفعات دون إسقاط العلاقات الاختيارية أو مضاعفة المقاييس، وتوقع عدد الصفوف الوسيطة قبل التجميع.

وقت القراءة التقريبي: 3 دقيقةتاريخ مراجعة المحتوى
في هذه الصفحة

أهداف الدرس

  • شرح الربط الداخلي والخارجي من قواعد المطابقة.
  • تجنب تضاعف المجاميع عند جمع علاقات فرعية متعددة.

حدد ما يمثله صف كل علاقة

يمثل صف العميل عميلاً وصف الحجز حجزاً. يولد ربط عميل بثلاثة حجوزات ثلاثة صفوف وتكرر خصائصه. يصح ذلك للتفاصيل ويخطر عند جمع رصيد يخص العميل. ابدأ بمستوى التقرير وحدد كل علاقة واحد إلى كثير. يتحقق المفتاح الخارجي من وجود الأصل لا من فرادة الفرع أو صلاحية جمع المال.

احفظ العميل دون حجوزات

تحتوي عينة VALUES الكاملة عميلين وحجزاً واحداً للعميل 1. يحفظ LEFT JOIN العميل 2 بأعمدة حجز NULL. المتوقع Lina مع 11 وOmar مع NULL؛ يحذف INNER JOIN عمر. لا يعني الربط الأيسر حفظ العميل بعد كل شرط لاحق؛ فقد يسقط WHERE على الفرع الصف الفارغ. موضع الشرط الاختياري جزء من السؤال التجاري.

sql SQL توضيحي؛ النتائج المتوقعة مستنتجة وليست قياسات.
SELECT c.customer_id, c.name, b.booking_id
FROM (VALUES (1, 'Lina'), (2, 'Omar')) AS c(customer_id, name)
LEFT JOIN (VALUES (11, 1)) AS b(booking_id, customer_id)
 ON b.customer_id = c.customer_id
ORDER BY c.customer_id;
الناتج المتوقع
customer_id | name | booking_id
1           | Lina | 11
2           | Omar | NULL

تعني NULL غياب حجز مطابق لا معرف حجز صفرياً.

ضع شروط الفرع الاختياري في ON

لتقرير جميع العملاء مع حجوزاتهم المدفوعة فقط ضع شرط الدفع بجانب المفتاح في ON. نقله إلى WHERE يسقط من كان فرعه NULL أو غير مدفوع. تبقى شروط نطاق العملاء الإلزامية في WHERE لأنها تختار المجموعة المطلوبة. أهل الأعمدة المشتركة مثل id وstate. تبسط USING المفاتيح المتطابقة، وافهم دمج أعمدتها قبل SELECT *.

استخدم EXISTS عند الحاجة للوجود فقط

يحتاج سؤال العملاء ذوي حجز مدفوع إلى الوجود لا التفاصيل المتكررة. تصرح EXISTS بالمطلوب دون تصنيع تكرارات لإزالتها بـ DISTINCT. تعيد العينة العميل 1 مرة رغم حجزين. يجب ربط المفاتيح الصحيحة؛ إهمال الشرط يسأل عن أي حجز في أي مكان، ويهم ذلك مع نطاق المؤسسة أو المستأجر.

sql SQL توضيحي؛ النتائج المتوقعة مستنتجة وليست قياسات.
SELECT c.customer_id
FROM (VALUES (1), (2)) AS c(customer_id)
WHERE EXISTS (
 SELECT 1 FROM (VALUES (11, 1), (12, 1)) AS b(booking_id, customer_id)
 WHERE b.customer_id = c.customer_id
) ORDER BY c.customer_id;
الناتج المتوقع
customer_id
1

تعيد EXISTS شرط حقيقة فلا يتكرر الأصل لكل فرع.

جمع الفروع مستقلة قبل ربط التقرير

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

الأخطاء الشائعة وإصلاحها

column reference is ambiguous (42702)

لماذا يحدث؟
استُخدم اسم عمود مشترك دون تأهيل.
كيف تصلحه؟
أهل الطرف مثل c.customer_id.
كيف تتجنب تكراره؟
استخدم أسماء مستعارة وإسقاطات صريحة.

يختفي العملاء الاختياريون من التقرير

لماذا يحدث؟
رفض WHERE صفوف الفرع الممتدة بـ NULL.
كيف تصلحه؟
انقل شرط الفرع الاختياري إلى ON إذا طابق المعنى.
كيف تتجنب تكراره؟
ضمّن أصلاً غير مطابق في عينة الربط الخارجي.

تكبر المجاميع بعد ربط فرع آخر

لماذا يحدث؟
تضاعفت علاقتان فرعيتان متعددتان.
كيف تصلحه؟
جمع الفرعين عند مستوى الأصل المشترك أولاً.
كيف تتجنب تكراره؟
وثق المستوى وتوقع أعداداً صغيرة قبل الجمع.

اختبر فهمك

1. للحجز بندان 10 و15 ودفعات 5 و8 و12. توقع المجاميع الصحيحة والخاطئة بالربط المباشر.

اعرض الحل المشروح

الصحيح 25 للبنود و25 للدفعات. يكرر الربط بستة صفوف البنود ثلاثاً فينتج 75 والدفعات مرتين فينتج 50. جمع كل فرع حسب booking_id ثم اربط ملخصاً واحداً، وحدد معنى غياب المجموع: صفر أم مجهول.

2. تحتاج العملاء بلا حجوزات. صف استعلام قراءة صحيحاً وافتراضه عن NULL.

اعرض الحل المشروح

استخدم NOT EXISTS مع مساواة المفتاحين. يصح LEFT JOIN ثم b.booking_id IS NULL إذا لم يقبل مفتاح الحجز الفراغ. قد يعتبر فحص وصف قابل للفراغ حجزاً موجوداً غائباً خطأ. احفظ قيود المستأجر في العلاقة حين يتطلب النموذج.

أهم ما تعلمته

  • تحدد تعددية الربط بقاء المقياس صحيحاً.
  • استخدم EXISTS للوجود وشروط ON الصريحة للفروع الاختيارية.

المراجع الرسمية