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

تحليل البيانات / المتوسط: العلاقات وعدم اليقين / الدرس 7

منطق استعلام SQL والمقامات الصريحة

حوّل التعريف التحليلي إلى شروط للصفوف وملخصات مجمعة وقواعد للقيم المفقودة وترتيب نتائج يمكن تكراره.

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

أهداف الدرس

  • تمييز WHERE من HAVING.
  • شرح NULL والمقامات وراء COUNT وAVG.
  • تحديد ترتيب حتمي ومدخلات ذات أنواع واضحة.

حدد المجتمع قبل الاستعلام

ابدأ بجملة مثل «مجموع المبالغ المعروفة للطلبات المفتوحة حسب المنطقة». حدد هل يمثل الصف طلباً أم بنداً، والحالات المؤهلة، وكيف تعامل المبلغ المجهول. تصف SELECT الخرج وتحدد FROM المدخل وتحتفظ WHERE بالصفوف التي يكون شرطها صحيحاً. يعلن SQL العلاقة المطلوبة، ولا يمثل ترتيب كتابته جدول التنفيذ المادي.

سجّل العدد قبل التصفية وبعدها؛ فقد ينجح الاستعلام ويجيب عن مجتمع آخر. لا تعوض مرونة أنواع التخزين في SQLite التحقق السابق، وقد يسبب النص العددي التالف سلوكاً تجميعياً مفاجئاً. تحمل الأمثلة قيماً مصطنعة محددة النوع في اتصال :memory: خاص وتغلقه صراحة دون استخدام قاعدة مهيأة.

افصل الصفوف المؤهلة من المجموعات المؤهلة

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

يبقي البرنامج North بمجموع ستين ويرفض South بمجموع خمسة وعشرين. وتعرض النتيجة الثانية أربعة صفوف مفتوحة وثلاثة مبالغ معروفة. تفصل المعلمات القيم عن بنية SQL. لا يغلق سياق معاملة sqlite3 الاتصال تلقائياً؛ لذلك تمتلك contextlib.closing عمر المورد هنا.

python تصفية الصفوف ثم المجموعات
import sqlite3
from contextlib import closing

with closing(sqlite3.connect(":memory:")) as db:
    db.execute("CREATE TABLE orders(region TEXT, status TEXT, amount REAL)")
    db.executemany("INSERT INTO orders VALUES (?, ?, ?)", [
        ("North", "open", 20.0), ("North", "open", 40.0),
        ("North", "closed", 200.0), ("South", "open", 25.0),
        ("South", "open", None),
    ])
    query = """SELECT region, COUNT(*), COUNT(amount), SUM(amount)
               FROM orders WHERE status = ? GROUP BY region
               HAVING SUM(amount) >= ?
               ORDER BY SUM(amount) DESC, region ASC"""
    print(db.execute(query, ("open", 50)).fetchall())
    print(db.execute("SELECT COUNT(*), COUNT(amount) FROM orders WHERE status = ?",
                     ("open",)).fetchone())
الناتج المتوقع
[('North', 2, 2, 60.0)]
(4, 3)

تجمع North المبلغين20 و40 ولا يشارك200 المغلق. ولـSouth صفان مفتوحان لكن مبلغاً معروفاً واحداً.

أظهر المجهول في المقام

تمثل NULL معلومة مفقودة لا صفراً أو نصاً فارغاً. لا تعثر amount = NULL عليها؛ استخدم IS NULL. تنتج المقارنة العادية مع NULL مجهولاً ولا تحتفظ WHERE بالمجهول. تعد COUNT(*) الصفوف وتعد COUNT(amount) المبالغ غير المفقودة، وتستخدم AVG(amount) المعروف بدلاً من اعتبار الغياب صفراً.

متوسط مبالغ الطلبات المفتوحة السابقة هو خمسة وثمانون على ثلاثة لا أربعة. اعرض تغطية القياس ومقامه عندما يهم الغياب. قد تعطي COALESCE بديلاً للعرض، لكن إدخالها في AVG يغير المقياس. احذر NOT IN إذا احتوت مجموعة المقارنة NULL؛ وغالباً توضح NOT EXISTS المرتبطة اختبار الغياب أكثر.

اجعل الاختيار والعرض قابلين للتكرار

لا يوجد ترتيب عرض مضمون دون ORDER BY. تختار LIMIT عدداً ولا تعني تلقائياً الأحدث أو الأكبر. أضف فاصلاً فريداً للتعادل عندما يلزم اختيار ثابت الحجم مستقر. يختار البرنامج أكبر مبلغين ويكسر تعادلهما بالمعرف؛ ولا يحل الفهرس أو ترتيب عرض سابق محل العقد.

توضح البيانات نفسها أن amount <> 0 يحتفظ بالمعرفين ثلاثة وأربعة ويستبعد الصفر وNULL. تختار IS NULL المعرف واحداً صراحة. كل نتيجة مرتبة فتكون القوائم المتوقعة ذات معنى. إن أردت كل المتعادلين عند الحد فحدد القاعدة مستقلة ولا تفترض أن LIMIT ثابتة تحفظهم.

python المجهول والصفر والاختيار المتعادل
import sqlite3
from contextlib import closing

with closing(sqlite3.connect(":memory:")) as db:
    db.execute("CREATE TABLE readings(id INTEGER PRIMARY KEY, amount REAL)")
    db.executemany("INSERT INTO readings VALUES (?, ?)",
                   [(1, None), (2, 0.0), (3, 10.0), (4, 10.0)])
    def ids(query):
        return [row[0] for row in db.execute(query)]
    print(ids("SELECT id FROM readings WHERE amount <> 0 ORDER BY id"))
    print(ids("SELECT id FROM readings WHERE amount IS NULL ORDER BY id"))
    print(ids("SELECT id FROM readings ORDER BY amount DESC, id ASC LIMIT 2"))
الناتج المتوقع
[3, 4]
[1]
[3, 4]

لا تنجح NULL في شرط عدم المساواة ويجدها فحص الغياب الصريح. يختار الترتيب النهائي3 و4 بحتمية.

دقق المعنى قبل تحسين الأداء

اكتب وحدة الخرج والشروط ومفاتيح التجميع وتعريف الدوال وسياسة الغياب بجانب الاستعلام. تسمح SQLite ببعض أعمدة التجميع غير المجمعة التي ترفضها محركات أشد صرامة؛ فلا تعتبر تسمية اعتباطية وصفاً موثوقاً للمجموعة. اختر تعبيرات ودوال مبررة واجعل قابلية النقل مطلباً صريحاً.

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

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

misuse of aggregate: SUM()

لماذا يحدث؟
وُضع اختبار مجموعة داخل WHERE.
كيف تصلحه؟
رشح المصدر بـWHERE والمجاميع المكتملة بـHAVING.
كيف تتجنب تكراره؟
حدد مرحلة كل شرط قبل كتابته.

عُدت المبالغ المجهولة أصفاراً مقاسة.

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

تغير أول صفين بين التشغيلات.

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

اختبر فهمك

1. لأربعة صفوف مبالغ20 و40 و25 وNULL. احسب الدوال الثلاث.

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

النتائج4 و3 و85/3 أي نحو28.333. يشارك الصف المفقود في عدد الأحداث لا متوسط المبالغ المقاسة. يحول استبداله بالصفر المقام إلى4، وهذا مقياس آخر لا تنظيف بريء.

2. لمنطقة طلبان مفتوحان30 و40 ومغلق200. اختر مجموع المفتوح الأكبر من50.

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

استخدم WHERE للحالة ثم GROUP BY للمنطقة ثم HAVING للمجموع. تتأهل بقيمة70. يحذف WHERE amount >50 الطلبين الصحيحين ويجيب عن سؤال آخر.

أهم ما تعلمته

  • تحدد الشروط المجتمع الممثل.
  • يختلف مقام COUNT(*) وCOUNT(value).
  • الترتيب وسياسة NULL ووحدة التجميع عقود صحة.

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