تحليل البيانات / المتوسط: العلاقات وعدم اليقين / الدرس 8
الربط وتعددية المطابقة وتغير وحدة السجل
اجمع الجداول دون مضاعفة القياسات أو إسقاط الكيانات غير المطابقة خفية، وميّز مطابقة الغياب في SQL من سلوك دمج pandas الموثق.
في هذه الصفحة
أهداف الدرس
- توقع صفوف الربط من تكرار المفاتيح.
- الحفاظ على الآباء غير المطابقين بقصد.
- تدقيق التضاعف والتغطية ودلالة المفاتيح المفقودة.
صرّح بالوحدتين والعلاقة المتوقعة
حدد معنى الصف في الجهتين وتفرد المفاتيح قبل الربط. قد يضم جدول العميل صفاً لكل عميل وجدول الطلب عدة صفوف له. ينتج الربط مطابقات على مستوى الطلب لا صفاً واحداً لكل عميل. لا يثبت اسم يشبه المفتاح الأساسي التفرد؛ افحص العقد وعدد التكرارات فعلاً.
صنّف العلاقة للمفتاح المختار: واحد لواحد أو واحد لمتعدد أو متعدد لواحد أو متعدد لمتعدد. إذا تكرر مفتاح a مرة يساراً وb مرة يميناً فقد تنتج a مضروبة في b من التركيبات المطابقة. توقع العدد قبل جمع مقياس، ووثق وحدة الخرج بوضوح وحدة العمود نفسه.
اقرأ الربط الخارجي صفاً بصف
يحفظ INNER JOIN التركيبات المتطابقة، ويضيف LEFT JOIN كل صف يساري بلا مطابقة مع NULL في أعمدة اليمين. لدى المثال ثلاثة عملاء: طلبان للأول وطلب للثاني ولا طلب للثالث، لذلك نتوقع أربعة صفوف. يعكس تكرار المعرف العلاقة وليس عيباً تمحوه DISTINCT.
إن أردت إرفاق الطلبات المؤهلة مع إبقاء كل العملاء فضع شرط الابن في ON. قد يرفض شرط WHERE على حالة اليمين الصف الموسع بـNULL فيسقط العميل غير المطابق. افحص الغياب بمفتاح يميني غير قابل للفقد، فقد تكون خاصية اختيارية NULL رغم وجود مطابقة حقيقية.
import sqlite3
from contextlib import closing
with closing(sqlite3.connect(":memory:")) as db:
db.executescript("""
CREATE TABLE customers(id INTEGER PRIMARY KEY);
CREATE TABLE orders(id INTEGER PRIMARY KEY, customer_id INTEGER, amount INTEGER);
""")
db.executemany("INSERT INTO customers VALUES (?)", [(1,), (2,), (3,)])
db.executemany("INSERT INTO orders VALUES (?, ?, ?)",
[(10, 1, 20), (11, 1, 30), (12, 2, 15)])
rows = db.execute("""SELECT c.id, o.id, o.amount
FROM customers AS c LEFT JOIN orders AS o
ON o.customer_id = c.id
ORDER BY c.id, o.id""").fetchall()
for row in rows:
print(row)
print("rows", len(rows))
(1, 10, 20)
(1, 11, 30)
(2, 12, 15)
(3, None, None)
rows 4
يظهر العميل1 مرتين والثاني مرة والثالث مرة بحقول طلب مفقودة؛ وتفسر الوحدة الصفوف الأربعة.
امنع التفاصيل المستقلة من مضاعفة المجاميع
قد يضاعف ربط تفصيلين مستقلين من نوع واحد لمتعدد تركيباتهما. ينتج طلب له بندان وثلاث دفعات ستة صفوف. إذا تكرر مبلغ الطلب عشرون فيها يصبح المجموع120 رغم أن الأصل20. يكشف البرنامج الثاني ذلك بجانب مجموع ضابط صحيح على مستوى الطلب.
جمّع كل تفصيل إلى الوحدة المشتركة المطلوبة قبل الدمج أو احسب مقاييس الرأس مستقلة. لا تصلح SUM(DISTINCT amount) المشكلة عموماً؛ فالطلبان المختلفان بالمبلغ نفسه كلاهما مشروع. تعمل DISTINCT على القيمة أو الأعمدة المعروضة لا تعريف الكيان غير المكتوب. افحص العدد وتكرار المفتاح بعد كل مرحلة.
import sqlite3
from contextlib import closing
with closing(sqlite3.connect(":memory:")) as db:
db.executescript("""
CREATE TABLE orders(id INTEGER PRIMARY KEY, amount INTEGER);
CREATE TABLE lines(id INTEGER PRIMARY KEY, order_id INTEGER);
CREATE TABLE payments(id INTEGER PRIMARY KEY, order_id INTEGER);
INSERT INTO orders VALUES (1, 20);
INSERT INTO lines VALUES (1, 1), (2, 1);
INSERT INTO payments VALUES (1, 1), (2, 1), (3, 1);
""")
joined = db.execute("""SELECT COUNT(*), SUM(o.amount) FROM orders AS o
JOIN lines AS l ON l.order_id = o.id
JOIN payments AS p ON p.order_id = o.id""").fetchone()
original = db.execute("SELECT COUNT(*), SUM(amount) FROM orders").fetchone()
matched = db.execute("""WITH a(k) AS (VALUES (NULL), (1)),
b(k) AS (VALUES (NULL), (1))
SELECT COUNT(*) FROM a JOIN b ON a.k = b.k""").fetchone()[0]
print("fanout", *joined)
print("order_grain", *original)
print("sql_null_matches", matched)
fanout 6 120
order_grain 1 20
sql_null_matches 1
ينتج بندان مضروبان في ثلاث دفعات ست نسخ من20. لا يطابق ربط المساواة للمفاتيح الاختيارية إلا المفتاح المعروف1.
لا تنقل افتراض الغياب بين الأدوات
لا تساوي NULL نفسها في ربط المساواة العادي في SQL، لذلك يشمل العدد الأخير المفتاح المعروف فقط. يحذر توثيق pandas.merge الرسمي من مطابقة المفاتيح المفقودة في الجهتين. قد يغير تحويل الخط من SQL إلى pandas العدد والمعنى رغم بقاء أسماء أعمدة المفاتيح ظاهرياً. ليست pandas مثبتة هنا ولا ندعي تنفيذها.
اختر سياسة صريحة: ارفض المفتاح المطلوب المفقود أو اعزله أو أبقه غير مطابق بتحويل موثق. تستطيع validate في pandas فحص العلاقة المتوقعة وتظهر indicator تغطية الدمج، لكنهما لا تثبتان صحة هوية الكيان. راجع الغياب قبل استبداله بقيمة رمزية قد تطابق صفوفاً كثيرة غير مرتبطة.
طابق التغطية والمفاتيح والقياسات
يقارن تدقيق الربط صفوف المصدر ومفاتيحه الفريدة وتكراراته والكيانات المطابقة والغائبة والمجاميع الضابطة. قد تكشف نسبة الاحتفاظ حسب الفئة إسقاط مجتمع بسبب مفتاح ناقص أو خريطة قديمة. لا تثبت نسبة مطابقة كلية مرتفعة تمثيل كل فئة مهمة؛ افحص عينة مضبوطة دون معرفات شخصية حقيقية.
ابنِ أمثلة فيها صفر وأحد وعدة أبناء ومبالغ متكررة ومفاتيح مفقودة. أكد وحدة النتيجة قبل الرسم أو تقدير عدم اليقين. يغير الربط الدليل؛ لذلك ينتمي تغير المقام والتعددية إلى التقرير لا ملاحظات تشخيص المطور وحدها.
الأخطاء الشائعة وإصلاحها
تجاوز مجموع الربط مجموع المصدر الضابط.
- لماذا يحدث؟
- ضاعفت علاقات أبناء مستقلة صفوف الرأس.
- كيف تصلحه؟
- جمّع بالوحدة المطلوبة قبل الربط أو افصل الرأس.
- كيف تتجنب تكراره؟
- افحص التكرار والمجاميع بعد كل ربط.
اختفى عملاء بلا طلب مؤهل.
- لماذا يحدث؟
- رفض شرط WHERE جهة NULL للربط الخارجي.
- كيف تصلحه؟
- ضع شرط تأهيل الابن في ON عند إبقاء كل الآباء.
- كيف تتجنب تكراره؟
- اختبر غياب الابن وغياب المؤهل.
طابقت ترجمة SQL إلى pandas مفاتيح مفقودة دون قصد.
- لماذا يحدث؟
- تختلف دلالة الغياب بين الأداتين.
- كيف تصلحه؟
- حدد سياسة المفتاح المفقود وافحصها قبل الدمج.
- كيف تتجنب تكراره؟
- أدرج الغياب في فحص التكافؤ بين الأدوات.
اختبر فهمك
1. لطلبين قيمة50 لكل منهما بندان. لماذا لا تصلح SUM(DISTINCT header.amount) الربط؟
اعرض الحل المشروح
المجموع المرتبط200 لكن DISTINCT تحتفظ بقيمة50 واحدة لا بهويتي طلب. الصحيح100. اجمع بالمعرف أو لخّص الطلبات مستقلة؛ تساوي المبلغ لا يعني تكرار الطلب.
2. لجدولي الربط مفتاح NULL ومفتاح1 في كل منهما. كيف يختلفان؟
اعرض الحل المشروح
يطابق SQL بالمساواة1 فقط وقد يطابق pandas الغياب أيضاً وفق توثيقه. قرر رفض المعرف المفقود أو إبقاءه غير مطابق واختبر السياسة بدلاً من افتراض الاتفاق.
أهم ما تعلمته
- ينتج الربط تركيبات يجب تحديد وحدتها.
- التغطية الغائبة والتضاعف سؤالا تدقيق منفصلان.
- قد تتغير مطابقة الغياب بتغير الأداة.