SELECT النجمة: تعلّم SQL بالقراءة والتمرين › الذيل الطويل 5 / 6 السابق التالي

الذيل الطويل

الذيول الطويلة

تشير الذيول الطويلة (long tails) إلى أعداد صغيرة من العينات التي تتكرر عددًا كبيرًا من المرات. وعندما نرسمها، تشكّل شريحة صغيرة بعيدة إلى يمين مركز الكتلة تشبه الذيل. وهي تدل على وجود قيم شاذة (outliers) قد تكون سلوكياتها غير المعتادة موضع اهتمام لنا. وفي سياق التنفيذ في تكساس، يشير الذيل الطويل إلى عدد صغير من المقاطعات عُرفت بتنفيذ عدد كبير من أحكام الإعدام.

لنجد النسبة المئوية للتنفيذ من كل مقاطعة حتى نتمكن من اختيار المقاطعات الواقعة في الذيل.

وكما سيصبح واضحًا أكثر فأكثر، يخبرنا شكل الجداول الكثير عن العمليات التي نحتاج إلى تنفيذها. (وهذا مماثل لتحليل الأبعاد في الفيزياء.) في هذه الحالة، نستطيع أن ندرك أن الطرق التي غطيناها حتى الآن غير كافية: فقد تعامل فصل Beazley مع صفوف بيانات فردية، لكن من الواضح أننا نحتاج إلى بعض التجميع لإيجاد بيانات على مستوى المقاطعة. وقد علّمنا فصل ادّعاءات البراءة التجميع، لكن تلك الدوال ستؤدي في النهاية إلى تجميع مجموعة البيانات في صف واحد، بينما نحن نريد صفًا واحدًا لكل مقاطعة.

كتلة GROUP BY

هنا تأتي كتلة GROUP BY. فهي تتيح لنا تقسيم مجموعة البيانات وتطبيق دوال تجميعية داخل كل مجموعة، بما ينتج صفًا واحدًا لكل مجموعة. وأبسط صيغة لها هي GROUP BY <column>, <column>, ... وتأتي بعد كتلة WHERE.

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

وربما لاحظت أيضًا استخدامنا لـ AS. وهو ما نسميه "إعطاء اسم مستعار" (aliasing). ففي كتلة SELECT، يوفّر <expression> AS <alias> اسمًا مستعارًا (alias) يمكن الرجوع إليه لاحقًا في الاستعلام. وهذا يوفّر علينا إعادة كتابة التعبيرات الطويلة، ويتيح لنا توضيح الغرض من التعبير.

كتلة HAVING

يوضح التمرين التالي أن التصفية عبر كتلة WHERE تحدث قبل تجميع الصفوف وحساب الدوال التجميعية. ويتجلى ذلك في ترتيب الصياغة، إذ تسبق كتلة WHERE دائمًا كتلة GROUP BY.

وكل هذا جيد، لكن ماذا يحدث إن أردنا التصفية بناءً على نتيجة التجميع والحساب التجميعي؟ بالتأكيد لا يمكننا القفز إلى المستقبل وانتزاع المعلومات من هناك. ولحلّ هذه المشكلة، نستخدم HAVING.

تدريب

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

استعلامات متداخلة

الآن، قد تسأل: ألن نكون قد انتهينا لو استطعنا فقط تشغيل شيء كهذا؟

SELECT
  county,
  PERCENT_COUNT(*)
FROM executions
GROUP BY county

النسب المئوية مقياس شائع إلى هذا الحد — ألا ينبغي أن توجد دالة كهذه؟ لسوء الحظ لا، وربما لسبب وجيه: فمثل هذه الدالة ستحتاج إلى التجميع داخل المجموعات (لحساب البسط) وعبر مجموعة البيانات كلها (لحساب المقام). لكن كل استعلام إما يحتوي على كتلة GROUP BY أو لا. فما نحتاجه حقًا هو استعلامان منفصلان، أحدهما يجمّع باستخدام GROUP BY والآخر يجمّع بدونه. ثم يمكننا دمجهما بتقنية تسمى "التداخل" (nesting).

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

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

لقد أدخلت بهدوء كتلة ORDER BY. صيغتها ORDER BY <column>, <column>, ... ويمكن تعديلها بإضافة DESC إن كنت لا تريد الترتيب التصاعدي الافتراضي.

مقاطعة Harris

هل يثير الدهشة أن Harris (موطن مدينة Houston) وDallas وBexar وTarrant تمثّل نحو 50% من كل عمليات التنفيذ في تكساس؟ ربما، خصوصًا إذا انطلقنا من افتراض أنه ينبغي أن تتوزع عمليات التنفيذ بالتساوي بين المقاطعات. لكن التقريب الأول الأفضل هو أن عمليات التنفيذ تتوزع بما يوازي توزيع السكان. ويوضح تعداد تكساس لعام 2010 أن عدد سكان المقاطعات الأربع كان 10.0 ملايين، أي 40.0% من سكان تكساس (25.1 مليونًا). وهذا يجعل النتيجة أقل إثارة للدهشة قليلًا.

لكن عند تفكيك هذا الذيل أكثر، ندرك أن مقاطعة Harris وحدها تمثّل معظم الفارق. فسكانها لا يشكلون سوى 16.4% من السكان، لكن عمليات التنفيذ فيها تمثّل 23.1%. وهذا أكثر بنحو 50% ممّا ينبغي أن يكون لها.

وقد فحصت دراسات عديدة سبب غزارة مقاطعة Harris، واقتُرح عدة عوامل:

الخلاصة

في هذا القسم، تعلّمنا التجميع عبر المجموعات واستخدام التداخل لاستخدام ناتج استعلام داخلي في استعلام خارجي. ولهذه التقنيات فائدة عملية بالغة، إذ تتيح لنا حساب النسب المئوية.

MapReduce

ومن الإضافات المثيرة للاهتمام أننا تعلّمنا للتو إجراء MapReduce في SQL. فـ MapReduce نموذج برمجي شهير ينظر إلى الحسابات على أنها تحدث في مرحلتي "map" و"reduce". ويمكنك معرفة المزيد عن MapReduce هنا.

كان فصل Beazley كله عن الـ mapping لأنه أرانا كيف نوزّع عمليات مختلفة على كل الصفوف. على سبيل المثال، SELECT LENGTH(last_statement) FROM executions توزّع دالة الطول على كل الصفوف. وهذا الفصل أرانا كيف نختزل مجموعات مختلفة من البيانات باستخدام دوال تجميعية؛ وكان الفصل السابق ادّعاءات البراءة مجرد حالة خاصة يكون فيها الجدول كله مجموعة واحدة.

وفي الفصل التالي، سنتعلم JOIN التي ستمكّننا من العمل مع جداول متعددة.