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

SQL Server / الأساسي / الدرس 4

ربط العلاقات واختبار الوجود

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

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

أهداف الدرس

  • توقع عدد صفوف الربط من المفاتيح.
  • الحفاظ على الصفوف غير المطابقة باستخدام LEFT JOIN بصورة صحيحة.
  • استخدام EXISTS وNOT EXISTS للوجود والغياب.

توقع عدد الصفوف

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

اربط بواسطة المفاتيح لا أسماء العرض؛ فقد يشترك عميلان في الاسم ويتغير الاسم لاحقاً. أهّل الأعمدة بأسماء مستعارة مقروءة لتجنب الالتباس. يعيد INNER JOIN التركيبات المطابقة فقط، ويعيد CROSS JOIN جميع التركيبات، وهو مفيد لإنشاء تقويم صغير أو مصفوفة اختبار عمداً. لكن فقد شرط الربط دون قصد قد يولد نتيجة ضخمة.

اقرأ نتائج الربط الداخلي والخارجي

يعطي المثال العميل 1 طلبين ولا يعطي العميل 2 أي طلب. يحافظ LEFT JOIN على العميلين ويضع NULL في أعمدة الطلب عند غياب المطابقة. الصفوف الثلاثة متوقعة، وليست تكراراً يتطلب DISTINCT. لن يغيّر حذف معرف الطلب وحدة الصف، بل سيخفيها. فسّر كل صف ناتج بعلاقة في البيانات الداخلة.

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

sql عميلان وعلاقة طلب اختيارية
WITH c AS (SELECT * FROM (VALUES (1,N'Aya'),(2,N'Omar'))v(CustomerId,Name)),
 o AS (SELECT * FROM (VALUES (10,1),(11,1))v(OrderId,CustomerId))
SELECT c.CustomerId,c.Name,o.OrderId
FROM c LEFT JOIN o ON o.CustomerId=c.CustomerId
ORDER BY c.CustomerId,o.OrderId;
الناتج المتوقع
CustomerId Name OrderId
1          Aya  10
1          Aya  11
2          Omar NULL

يظهر العميل 1 مرة لكل مطابقة ويحصل العميل 2 على صف موسع بـ NULL لغياب الطلب.

ضع شروط الجهة الاختيارية بقصد

لعرض جميع العملاء مع الطلبات المفتوحة إن وجدت، ضع شرط الطلب المفتوح داخل ON في LEFT JOIN. إن وضعت o.Status = N'Open' في WHERE فستحذف العملاء غير المطابقين لأن حالتهم NULL وتنتج المقارنة UNKNOWN. يجيب الاستعلامان عن سؤالين مختلفين رغم احتوائهما LEFT JOIN.

تحدد ON الأزواج المتطابقة، ثم تصفّي WHERE الصفوف الناتجة. يكتسب الفرق أهمية خاصة مع حدود المستأجرين وتواريخ السريان وصفوف الأبناء المحذوفة منطقياً. لا تنقل شرطاً لمجرد تقصير الاستعلام. حدد أولاً هل يجب أن يبقى الأب دون ابن مؤهل مرئياً، ثم ضع الشرط بما يحقق هذا القرار.

اطرح أسئلة الوجود مباشرة

تختبر EXISTS هل يجد الاستعلام الفرعي المرتبط أي صف. لا تؤثر قيمة الثابت المختار في قرار الوجود. ولأن صف العميل الخارجي لا يتضاعف بعدد طلباته، تناسب EXISTS سؤال العملاء الذين طلبوا. وتعبّر NOT EXISTS عن العملاء دون طلب مطابق وتتجنب فخ NULL في NOT IN.

يعيد المثال العميل 2. لن تؤثر إضافة قيمة أخرى قابلة لـ NULL داخل صف الطلب في قرار الارتباط. لكن يجب أن يكون الارتباط نفسه صحيحاً عند اختبار الغياب؛ فحذف مقارنة العميل يحوّل السؤال إلى هل مصدر الطلبات كله فارغ. اقرأ الاستعلام الفرعي بصيغة «طلب لهذا العميل» لا مجرد «طلب».

sql اعثر على العميل دون طلب
WITH c AS (SELECT * FROM (VALUES (1),(2))v(CustomerId)),
 o AS (SELECT * FROM (VALUES (10,1),(11,1))v(OrderId,CustomerId))
SELECT c.CustomerId FROM c
WHERE NOT EXISTS (SELECT 1 FROM o WHERE o.CustomerId=c.CustomerId)
ORDER BY c.CustomerId;
الناتج المتوقع
CustomerId
2

تعني المطابقتان للعميل 1 وجود طلب، بينما يبقى العميل 2 لغياب أي مطابقة.

تحقق بأمثلة مضادة صغيرة

ابنِ بيانات اختبار فيها أب بلا أبناء، وآخر له ابن واحد، وثالث له عدة أبناء. أضف أبوين بالاسم المعروض نفسه وخاصية اختيارية مفقودة حيث تسمح البنية. تكشف هذه الحالات مفاتيح الربط الخاطئة وسلوك الربط الداخلي غير المقصود أسرع من فحص شبكة كبيرة واقعية. قارن مجموعات المفاتيح وتكراراتها لا عدد الصفوف وحده.

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

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

The multi-part identifier could not be bound.

لماذا يحدث؟
يستخدم العمود اسماً مستعاراً غير موجود في النطاق.
كيف تصلحه؟
صحح الاسم المستعار وأهّل العلاقة باتساق.
كيف تتجنب تكراره؟
استخدم أسماء مختصرة مستقرة وراجع النطاق.

Customers without orders disappeared.

لماذا يحدث؟
يرفض شرط WHERE جهة NULL في LEFT JOIN.
كيف تصلحه؟
انقل شرط تأهيل الابن إلى ON إذا وجب بقاء الآباء.
كيف تتجنب تكراره؟
حدد أولاً متطلب الآباء بلا مطابقة.

Order amounts are counted repeatedly.

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

اختبر فهمك

1. للعميل طلبان ولكل طلب ثلاثة بنود. كم صفاً ينتج الربط الداخلي؟

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

ستة صفوف على مستوى البند. جمع مبلغ الرأس عليها يحسب كل طلب ثلاث مرات. اجمع مبالغ البنود حسب الطلب أو اجمع الرؤوس مستقلة قبل دمج النتائج.

2. احتفظ بكل العملاء وأرفق طلبات يناير فقط. أين تضع شرط التاريخ؟

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

ضع مجال يناير نصف المفتوح في ON لـ LEFT JOIN مع مساواة مفتاح العميل. سيرفض شرط WHERE على تاريخ الطلب الاختياري العملاء دون مطابقة في يناير.

أهم ما تعلمته

  • يحفظ الربط التركيبات لا وحدة عمل مفترضة.
  • تختلف وظيفة ON وWHERE في الربط الخارجي.
  • تعبّر EXISTS عن الوجود دون مضاعفة الصف الخارجي.

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