
MySQL Joins وUNION وGROUP BY وHAVING وSQL المتقدم
لا يقتصر MySQL على تحديد الصفوف من جدول واحد فقط. يتطلب عمل database الحقيقي عادةً دمج الجداول المرتبطة، وتصفية النتائج المجمعة، ومقارنة القيم مع الاستعلامات الفرعية، ونسخ البيانات بين الجداول، ومعالجة قيم NULL بشكل صحيح، وكتابة منطق database القابل لإعادة الاستخدام.
تشرح هذه المقالة موضوعات MySQL المتقدمة الموضحة في مسار التعلم: joins، INNER JOIN، LEFT JOIN، RIGHT JOIN، CROSS JOIN، self join، UNION، UNION ALL، GROUP BY، HAVING، EXISTS، ANY، ALL، INSERT SELECT، CASE، وظائف NULL وstored procedures والتعليقات وoperators.
الهدف ليس فقط حفظ بناء الجملة. الهدف هو فهم متى يجب استخدام كل ميزة، وكيف تتصرف، وما هي الأخطاء التي يجب على المطورين تجنبها عند كتابة استعلامات MySQL الحقيقية.
MySQL Joins
يتم استخدام join لدمج صفوف من جدولين أو أكثر بناءً على عمود مرتبط بينهما. في databases العلائقية، يتم تقسيم البيانات عادةً إلى جداول متعددة لتجنب التكرار والحفاظ على التصميم نظيفًا. على سبيل المثال، قد يتم تخزين العملاء في جدول واحد، بينما يتم تخزين الطلبات في جدول آخر.
بدون الصلات، ستحتاج إلى الاستعلام عن كل جدول على حدة وتوصيل البيانات يدويًا في تطبيقك. باستخدام الصلات، يمكن لـ MySQL إرجاع البيانات ذات الصلة في استعلام واحد.
لنفترض أن لدينا جدولين بسيطين:
customers
+----+---------+
| id | name |
+----+---------+
| 1 | Adnan |
| 2 | Noor |
| 3 | Sara |
+----+---------+
orders
+----+-------------+--------+
| id | customer_id | total |
+----+-------------+--------+
| 1 | 1 | 120.00 |
| 2 | 1 | 80.00 |
| 3 | 2 | 50.00 |
+----+-------------+--------+العلاقة واضحة:Orders.customer_idيشير إلىcustomer.id. يتيح لنا الانضمام إظهار اسم العميل بجانب كل طلب.
SELECT
customers.name,
orders.total
FROM customers
JOIN orders
ON customers.id = orders.customer_id;التشغيلالشرط يخبر MySQL بكيفية ارتباط الجداول. بدون شرط صلة صحيح، يمكن أن تصبح النتيجة غير صحيحة أو كبيرة للغاية.
في المشاريع الاحترافية، يتم استخدام الصلات باستمرار في التقارير ولوحات المعلومات ولوحات الإدارة وصفحات search والفواتير وأذونات المستخدم وكتالوجات المنتجات واستعلامات التحليلات.
MySQL INNER JOIN
INNER JOINتُرجع فقط الصفوف التي تحتوي على قيم متطابقة في كلا الجدولين. إذا لم يكن لدى العميل أي طلبات، فلن يظهر هذا العميل في النتيجة. إذا كان الطلب يشير إلى عميل مفقود، فلن يظهر هذا الطلب أيضًا.
SELECT
c.id,
c.name,
o.id AS order_id,
o.total
FROM customers AS c
INNER JOIN orders AS o
ON c.id = o.customer_id;هنا،جوسهي الجدول aliases. الأسماء المستعارة تجعل الاستعلامات أقصر وأسهل في القراءة، خاصة عند ضم عدة جداول.
استخدم INNER JOIN عندما تريد فقط السجلات الموجودة على جانبي العلاقة. تشمل الأمثلة الشائعة ما يلي:
الطلبات التي تخص العملاء الحاليين.
التعليقات التي تنتمي إلى المشاركات الموجودة.
المنتجات التي تنتمي إلى classes الموجودة.
المدفوعات التي تنتمي إلى الفواتير الموجودة.
في MySQL، الكتابةJOINدون تحديد النوع يعني عادةINNER JOIN.
MySQL LEFT JOIN
LEFT JOINإرجاع كافة الصفوف من الجدول الأيسر والصفوف المطابقة من الجدول الأيمن. إذا لم يكن هناك تطابق، فسيتم إرجاع MySQLNULLلأعمدة الجدول الصحيحة.
يكون هذا مفيدًا عندما يجب أن يظهر الجدول الرئيسي دائمًا، حتى في حالة عدم وجود السجلات المرتبطة.
SELECT
c.id,
c.name,
o.id AS order_id,
o.total
FROM customers AS c
LEFT JOIN orders AS o
ON c.id = o.customer_id;يقوم هذا الاستعلام بإرجاع كافة العملاء. سيظهر العملاء الذين لديهم طلبات مع بيانات الطلب. سيظل العملاء الذين ليس لديهم طلبات يظهرون، لكن أعمدة الطلب ستحتوي على NULL.
يُستخدم LEFT JOIN بشكل شائع للعثور على البيانات ذات الصلة المفقودة. على سبيل المثال، للعثور على العملاء الذين لم يقدموا طلبًا مطلقًا:
SELECT
c.id,
c.name
FROM customers AS c
LEFT JOIN orders AS o
ON c.id = o.customer_id
WHERE o.id IS NULL;الحالةWHERE o.id هو NULLيحتفظ فقط بالصفوف التي لا يوجد بها ترتيب مطابق.
من الأخطاء الشائعة وضع مرشحات الجدول الأيمن في جملة WHERE عند استخدام LEFT JOIN. على سبيل المثال، إذا كنت تكتبWHERE o.status = 'مدفوع'، قد يتصرف الاستعلام مثل INNER JOIN لأن الصفوف التي لا تحتوي على أوامر لها قيم NULL. للحفاظ على سلوك LEFT JOIN، ضع مرشحات الجانب الأيمن الاختيارية داخل حالة التشغيل عندما يكون ذلك مناسبًا.
SELECT
c.id,
c.name,
o.total
FROM customers AS c
LEFT JOIN orders AS o
ON c.id = o.customer_id
AND o.status = 'paid';MySQL RIGHT JOIN
RIGHT JOINإرجاع كافة الصفوف من الجدول الأيمن والصفوف المطابقة من الجدول الأيسر. إذا لم يكن هناك أي تطابق، تقوم MySQL بإرجاع NULL لأعمدة الجدول اليسرى.
SELECT
c.name,
o.id AS order_id,
o.total
FROM customers AS c
RIGHT JOIN orders AS o
ON c.id = o.customer_id;يقوم هذا الاستعلام بإرجاع جميع الطلبات، حتى لو لم يكن لدى بعض الطلبات عميل مطابق. في database المصمم جيدًا مع قيود المفاتيح الخارجية، يجب عادةً منع هذا الموقف.
RIGHT JOIN هو SQL صالح، لكن العديد من المطورين يفضلون إعادة كتابته كـ LEFT JOIN عن طريق تبديل ترتيب الجدول. عادةً ما يكون LEFT JOIN أسهل في القراءة لأن الجدول الرئيسي يظهر أولاً.
SELECT
c.name,
o.id AS order_id,
o.total
FROM orders AS o
LEFT JOIN customers AS c
ON c.id = o.customer_id;عادةً ما ينقل هذا الإصدار النية بشكل أكثر وضوحًا: إرجاع جميع الطلبات وإرفاق بيانات العميل عند توفرها.
MySQL CROSS JOIN
CROSS JOINإرجاع المنتج الديكارتي لجدولين. وهذا يعني أنه يتم دمج كل صف من الجدول الأول مع كل صف من الجدول الثاني.
إذا كان الجدول الأول يحتوي على 3 صفوف والجدول الثاني يحتوي على 4 صفوف، فستحتوي النتيجة على 12 صفًا.
SELECT
s.size,
c.color
FROM sizes AS s
CROSS JOIN colors AS c;يمكن أن يكون ذلك مفيدًا عند إنشاء جميع المجموعات الممكنة، مثل أحجام المنتج وألوانه، وتواريخ التقويم والفترات الزمنية، أو الخيارات المتاحة في نظام التكوين.
يجب استخدام CROSS JOIN بعناية. على الطاولات الكبيرة، يمكن أن يحقق نتيجة ضخمة بسرعة كبيرة. على سبيل المثال، يؤدي ضم 10000 صف إلى 10000 صف إلى إنتاج 100000000 مجموعة.
MySQL self join
أself joinهي صلة حيث يتم ضم الجدول إلى نفسه. يكون ذلك مفيدًا عندما تكون الصفوف الموجودة في نفس الجدول مرتبطة بصفوف أخرى في نفس الجدول.
ومن الأمثلة الشائعة جدول الموظفين حيث قد يكون لكل موظف مدير. المدير هو أيضًا موظف في نفس الجدول.
SELECT
e.name AS employee_name,
m.name AS manager_name
FROM employees AS e
LEFT JOIN employees AS m
ON e.manager_id = m.id;يتم استخدام الجدول مرتين، ولكن مع aliases مختلفة:هللموظفين ومللمديرين. بدون aliases، لن يعرف MySQL إصدار الجدول الذي تقصده.
يتم أيضًا استخدام الصلات الذاتية لأشجار classes وأنظمة الإحالة والعلاقات بين الوالدين والطفل والتعليقات المترابطة والهياكل التنظيمية والبيانات الهرمية.
MySQL UNION
UNIONيجمع نتيجة استعلامين SELECT أو أكثر في مجموعة نتائج واحدة. يجب أن تقوم عبارات SELECT بإرجاع نفس عدد الأعمدة، ويجب أن تحتوي الأعمدة على أنواع بيانات متوافقة.
SELECT email FROM customers
UNION
SELECT email FROM subscribers;يعرض هذا الاستعلام قائمة مجمعة من رسائل البريد الإلكتروني الواردة من العملاء والمشتركين. بشكل افتراضي، يقوم UNION بإزالة الصفوف المكررة.
يكون UNION مفيدًا عندما تأتي البيانات من مصادر مختلفة ولكن يجب عرضها كقائمة واحدة. على سبيل المثال، يمكنك دمج المستخدمين النشطين والمستخدمين المدعوين، أو الطلبات القديمة والطلبات الجديدة، أو نتائج search من جداول متعددة.
عادةً ما تأتي أسماء الأعمدة في النتيجة النهائية من عبارة SELECT الأولى.
SELECT name AS person_name, email FROM customers
UNION
SELECT full_name, email_address FROM leads;على الرغم من أن SELECT الثاني يستخدم أسماء أعمدة مختلفة، إلا أن الإخراج النهائي يستخدم aliases من SELECT الأول.
إذا كنت بحاجة إلى فرز النتيجة المجمعة النهائية، ضع ORDER BY في نهاية استعلام UNION الكامل، وليس داخل كل SELECT إلا إذا كنت تستخدم استعلامات فرعية لسبب محدد.
SELECT name, email FROM customers
UNION
SELECT full_name, email_address FROM leads
ORDER BY name;MySQL UNION ALL
UNION ALLيجمع أيضًا نتائج SELECT المتعددة، لكنه لا يزيل التكرارات. وهذا يجعله أسرع من UNION في العديد من الحالات لأن MySQL لا يحتاج إلى إجراء إزالة مكررة.
SELECT email FROM customers
UNION ALL
SELECT email FROM subscribers;استخدم UNION ALL عندما تكون الصفوف المكررة مقبولة أو ذات معنى. على سبيل المثال، إذا كنت تقوم بدمج سجلات من جداول مختلفة، فقد تمثل القيم المتكررة events منفصلة حقيقية ويجب عدم إزالتها.
القاعدة العملية بسيطة: استخدم UNION عندما تحتاج على وجه التحديد إلى صفوف فريدة؛ استخدم UNION ALL عندما تريد كافة الصفوف تمامًا كما تأتي من عبارات SELECT.
MySQL GROUP BY
GROUP BYمجموعات الصفوف التي لها نفس القيمة في عمود واحد أو أكثر. يتم استخدامه عادةً مع الوظائف المجمعة مثل COUNT() وSUM() وAVG() وMIN() وMAX().
على سبيل المثال، لحساب إجمالي مبلغ المبيعات لكل عميل:
SELECT
customer_id,
SUM(total) AS total_spent
FROM orders
GROUP BY customer_id;لا يُرجع هذا الاستعلام صفًا واحدًا لكل طلب. تقوم بإرجاع صف واحد لكل عميل، لأنه يتم تجميع الصفوف حسب customer_id.
يمكنك أيضًا التجميع حسب أعمدة متعددة. على سبيل المثال، المبيعات لكل عميل لكل حالة:
SELECT
customer_id,
status,
COUNT(*) AS orders_count,
SUM(total) AS total_amount
FROM orders
GROUP BY customer_id, status;يستخدم GROUP BY بكثافة في إعداد التقارير والتحليلات. يساعد في الإجابة على أسئلة مثل:
كم عدد الطلبات لدى كل عميل؟
ما هو إجمالي الإيرادات شهريا؟
كم عدد المشاركات في كل class؟
ما هو متوسط الراتب لكل قسم؟
عند تشغيل MySQL بقواعد تجميع صارمة، يجب أن يكون كل عمود محدد إما جزءًا من GROUP BY أو يتم استخدامه داخل دالة تجميعية، ما لم يتمكن MySQL من تحديد أن العمود يعتمد وظيفيًا على العمود المجمع. تمنع هذه القاعدة النتائج غير الواضحة.
MySQL HAVING
HAVINGتصفية النتائج المجمعة. إنه مشابه لـ WHERE، لكن WHERE يقوم بتصفية الصفوف قبل التجميع، بينما يقوم HAVING بتصفية المجموعات بعد aggregation.
على سبيل المثال، لإظهار العملاء الذين يزيد إجمالي إنفاقهم عن 1000 فقط:
SELECT
customer_id,
SUM(total) AS total_spent
FROM orders
GROUP BY customer_id
HAVING SUM(total) > 1000;لا يمكن استخدام WHERE مباشرة مع النتائج المجمعة مثل SUM(الإجمالي) بنفس الطريقة لأن WHERE يعمل قبل إنشاء المجموعات.
النمط الشائع هو استخدام WHERE لمرشحات الصف العادية وHAVING لمرشحات التجميع:
SELECT
customer_id,
COUNT(*) AS paid_orders
FROM orders
WHERE status = 'paid'
GROUP BY customer_id
HAVING COUNT(*) >= 3;في هذا الاستعلام، يحتفظ WHERE أولاً بالطلبات المدفوعة فقط. ثم يقوم GROUP BY بتجميع تلك الطلبات المدفوعة بواسطة العميل. وأخيرًا، يحتفظ HAVING فقط بالعملاء الذين لديهم ثلاثة طلبات مدفوعة على الأقل.
MySQL EXISTS
EXISTSيتحقق مما إذا كان الاستعلام الفرعي يُرجع صفًا واحدًا على الأقل. يتم إرجاعه صحيحًا إذا عثر الاستعلام الفرعي على أي سجل مطابق.
على سبيل المثال، للحصول على العملاء الذين لديهم طلب واحد على الأقل:
SELECT
c.id,
c.name
FROM customers AS c
WHERE EXISTS (
SELECT 1
FROM orders AS o
WHERE o.customer_id = c.id
);يتم توصيل الاستعلام الفرعي بالاستعلام الخارجي من خلالo.customer_id = c.id. وهذا ما يسمى باستعلام فرعي مرتبط لأن الاستعلام الداخلي يعتمد على الصف الحالي من الاستعلام الخارجي.
يُستخدم EXISTS غالبًا عندما تهتم بوجود صفوف مرتبطة، وليس بإرجاع القيم منها.
للعثور على عملاء ليس لديهم طلبات، استخدم NOT EXISTS:
SELECT
c.id,
c.name
FROM customers AS c
WHERE NOT EXISTS (
SELECT 1
FROM orders AS o
WHERE o.customer_id = c.id
);NOT EXISTS عادة ما تكون طريقة واضحة وآمنة للتعبير عن منطق منع الانضمام، خاصة عندما تؤدي قيم NULL إلى جعل NOT IN تتصرف بشكل غير متوقع.
MySQL ANY
ANYيقارن قيمة مع أي قيمة يتم إرجاعها بواسطة استعلام فرعي. يتم إرجاعه صحيحًا إذا كانت المقارنة صحيحة لقيمة واحدة على الأقل في نتيجة الاستعلام الفرعي.
يتم استخدام ANY مع المقارنة operators مثل =، >، <، >=، <=، و<>.
SELECT
product_name,
price
FROM products
WHERE price > ANY (
SELECT price
FROM products
WHERE category_id = 5
);يقوم هذا الاستعلام بإرجاع المنتجات التي يزيد سعرها عن سعر منتج واحد على الأقل في class 5.
مثال آخر: ابحث عن الأوامر التي يساوي إجماليها أي إجمالي من الأوامر ذات الأولوية العالية:
SELECT
id,
total
FROM orders
WHERE total = ANY (
SELECT total
FROM orders
WHERE priority = 'high'
);في كثير من المواقف،= ANYيشبهفي. ومع ذلك، ANY أكثر عمومية لأنه يمكن استخدامه مع مقارنة مختلفة operators.
MySQL ALL
ALLيقارن قيمة مع كل قيمة يتم إرجاعها بواسطة استعلام فرعي. يتم إرجاعه صحيحًا فقط إذا كانت المقارنة صحيحة لجميع القيم الموجودة في نتيجة الاستعلام الفرعي.
SELECT
product_name,
price
FROM products
WHERE price > ALL (
SELECT price
FROM products
WHERE category_id = 5
);يقوم هذا الاستعلام بإرجاع المنتجات التي يزيد سعرها عن كل سعر منتج في class 5. بمعنى آخر، يجب أن يكون سعر المنتج أعلى من الحد الأقصى للسعر الموجود في تلك class.
يكون ALL مفيدًا عندما يتطلب المنطق قيمة لتمرير مقارنة مع نتيجة الاستعلام الفرعي بالكامل، وليس صفًا واحدًا فقط.
ANY وALL قويان، لكن يجب استخدامهما بحذر. في كثير من الحالات، يمكن كتابة نفس المنطق باستخدام MIN()، أو MAX()، أو EXISTS، أو الصلات، والتي قد يكون من الأسهل على المطورين الآخرين فهمها.
MySQL INSERT SELECT
INSERT SELECTيقوم بإدراج البيانات في جدول باستخدام نتيجة استعلام SELECT. يكون ذلك مفيدًا عند نسخ البيانات أو أرشفة السجلات أو إنشاء التقارير أو ترحيل الصفوف المحددة أو إعداد جداول التلخيص.
INSERT INTO archived_orders (order_id, customer_id, total, archived_at)
SELECT
id,
customer_id,
total,
NOW()
FROM orders
WHERE status = 'completed'
AND created_at < '2025-01-01';يجب أن تتطابق الأعمدة الموجودة في القائمة INSERT مع عدد القيم التي يتم إرجاعها بواسطة الاستعلام SELECT وأنواعها المتوافقة.
يمكنك أيضًا الإدراج في جدول واحد من جدول آخر بنفس البنية:
INSERT INTO customers_backup (id, name, email)
SELECT id, name, email
FROM customers;قبل تشغيل INSERT SELECT على بيانات الإنتاج، من الحكمة تشغيل الجزء SELECT بمفرده أولاً للتأكد من الصفوف التي سيتم إدراجها بالضبط.
MySQL CASE
CASEيضيف المنطق الشرطي داخل استعلام SQL. يسمح لك بإرجاع قيم مختلفة حسب الظروف.
يعد CASE مفيدًا للتسميات القابلة للقراءة والأعمدة المحسوبة والفرز المخصص وaggregation المشروط وتنسيق التقارير.
SELECT
id,
total,
CASE
WHEN total >= 1000 THEN 'High'
WHEN total >= 500 THEN 'Medium'
ELSE 'Low'
END AS order_value
FROM orders;يقوم هذا الاستعلام بإنشاء عمود محسوب يسمىorder_value. القيمة تعتمد على إجمالي الطلب.
يمكن أيضًا استخدام CASE مع تقارير GROUP BY. على سبيل المثال، حساب الطلبات حسب مستوى القيمة:
SELECT
CASE
WHEN total >= 1000 THEN 'High'
WHEN total >= 500 THEN 'Medium'
ELSE 'Low'
END AS value_level,
COUNT(*) AS orders_count
FROM orders
GROUP BY value_level;CASE لا يغير البيانات المخزنة. إنه يغير فقط كيفية إرجاع القيم في نتيجة الاستعلام.
هناك نوعان شائعان من CASE: CASE الذي تم البحث عنه وCASE البسيط. تم البحث عن CASE للتحقق من الشروط الكاملة. يقارن CASE البسيط تعبيرًا واحدًا بقيم متعددة.
SELECT
id,
status,
CASE status
WHEN 'paid' THEN 'Payment received'
WHEN 'pending' THEN 'Waiting for payment'
WHEN 'cancelled' THEN 'Order cancelled'
ELSE 'Unknown status'
END AS status_label
FROM orders;MySQL وظائف فارغة
NULL يعني مفقود أو غير معروف أو غير قابل للتطبيق. إنها ليست مثل الصفر، أو سلسلة فارغة، أو خطأ. نظرًا لأن NULL يمثل قيمة غير معروفة، فقد تتصرف المقارنات العادية بشكل مختلف عما يتوقعه المبتدئون.
على سبيل المثال، هذا الشرط خاطئ:
SELECT * FROM users
WHERE deleted_at = NULL;للتحقق من NULL، استخدمهو NULLأوهو NOT NULL:
SELECT * FROM users
WHERE deleted_at IS NULL;يوفر MySQL العديد من الوظائف للعمل مع قيم NULL.
IFNULL()تُرجع قيمة بديلة عندما تكون القيمة الأولى هي NULL:
SELECT
name,
IFNULL(phone, 'No phone number') AS phone_display
FROM customers;التئام()تقوم بإرجاع القيمة الأولى غير NULL من القائمة. يكون ذلك مفيدًا عندما تكون هناك عدة قيم احتياطية ممكنة:
SELECT
name,
COALESCE(work_phone, mobile_phone, home_phone, 'No phone') AS contact_phone
FROM customers;نوليف ()تُرجع NULL إذا كان هناك تعبيران متساويان؛ وإلا فإنه يقوم بإرجاع التعبير الأول:
SELECT
product_name,
NULLIF(discount_price, regular_price) AS real_discount_price
FROM products;تعتبر الوظائف الخالية مهمة في التقارير لأن الحسابات المجمعة وقيم العرض يمكن أن تصبح مربكة إذا تم تجاهل قيم NULL أو معالجتها بشكل غير صحيح.
MySQL الإجراءات المخزنة
الإجراء المخزن عبارة عن كتلة قابلة لإعادة الاستخدام من كود SQL المخزنة داخل database. بدلاً من إرسال نفس منطق SQL من التطبيق في كل مرة، يمكنك استدعاء الإجراء بالاسم.
يمكن للإجراءات المخزنة قبول المعلمات وتنفيذ عبارات متعددة واستخدام المتغيرات وتضمين المنطق الشرطي وإرجاع مجموعات النتائج.
DELIMITER //
CREATE PROCEDURE GetCustomerOrders(IN customerId INT)
BEGIN
SELECT
id,
total,
status,
created_at
FROM orders
WHERE customer_id = customerId
ORDER BY created_at DESC;
END //
DELIMITER ;بعد إنشاء الإجراء، يمكنك تسميته مثل هذا:
CALL GetCustomerOrders(1);المحدديتم استخدام command في العديد من عملاء MySQL لأن نص الإجراء يحتوي على فواصل منقوطة. يسمح تغيير المحدد مؤقتًا بمعاملة تعريف الإجراء بأكمله كبيان واحد.
يمكن أن تكون الإجراءات المخزنة مفيدة للعمليات من جانب database، ومنطق التقارير المتكررة، والأنظمة القديمة، والتحكم في الوصول إلى عمليات محددة. ومع ذلك، لا ينبغي الإفراط في استخدامها كبديل لبنية التطبيقات النظيفة. في العديد من تطبيقات الويب الحديثة، غالبًا ما يتم الاحتفاظ بـ منطق العمل في طبقة التطبيق، بينما يتم استخدام stored procedures فقط عندما توفر فائدة واضحة.
يمكن أن يبدو الإجراء المخزن مع معلمة الإخراج كما يلي:
DELIMITER //
CREATE PROCEDURE CountCustomerOrders(
IN customerId INT,
OUT ordersCount INT
)
BEGIN
SELECT COUNT(*)
INTO ordersCount
FROM orders
WHERE customer_id = customerId;
END //
DELIMITER ;
CALL CountCustomerOrders(1, @count);
SELECT @count AS orders_count;تعليقات MySQL
التعليقات هي ملاحظات مكتوبة داخل كود SQL. يتجاهلها MySQL أثناء التنفيذ. فهي تساعد في شرح الاستعلامات المعقدة أو قرارات document أو تعطيل جزء من الاستعلام مؤقتًا أثناء الاختبار.
يدعم MySQL التعليقات ذات السطر الواحد باستخدام--أو#:
-- Get active customers only
SELECT *
FROM customers
WHERE status = 'active';
# This is also a single-line comment
SELECT COUNT(*) FROM orders;يدعم MySQL أيضًا التعليقات متعددة الأسطر باستخدام/*... */:
/*
This query calculates total revenue
from paid orders only.
*/
SELECT
SUM(total) AS revenue
FROM orders
WHERE status = 'paid';يجب أن توضح التعليقات سبب القيام بشيء ما، وليس تكرار ما يقوله SQL بالفعل. التعليقات الجيدة مفيدة في عمليات الانضمام المعقدة والتقارير وعمليات الترحيل والبرامج النصية للصيانة.
مشغلي MySQL
عوامل التشغيل هي رموز أو كلمات رئيسية تستخدم لإجراء العمليات الحسابية والمقارنات والشروط المنطقية ومطابقة الأنماط. وهي جزء من كل استعلام SQL تقريبًا.
يتم استخدام الحساب operators لإجراء العمليات الحسابية:
SELECT
price,
quantity,
price * quantity AS line_total
FROM order_items;تشمل العمليات الحسابية الشائعة operators+,-,*,/، و%.
مقارنة operators مقارنة القيم:
SELECT *
FROM products
WHERE price >= 100
AND stock <> 0;تشمل المقارنة الشائعة operators=,<>,!=,>,<,>=، و<=.
شروط الجمع المنطقية operators:
SELECT *
FROM orders
WHERE status = 'paid'
AND total > 500;operators المنطقية الأكثر شيوعًا هيو,أو، ولا. ينبغي استخدام الأقواس عند الجمع بين AND وOR لتجنب المنطق غير الواضح.
SELECT *
FROM orders
WHERE status = 'paid'
AND (total > 500 OR priority = 'high');يتم استخدام النمط والنطاق operators للتصفية المرنة:
SELECT *
FROM customers
WHERE name LIKE 'A%'
AND city IN ('Istanbul', 'Samsun', 'Ankara')
AND created_at BETWEEN '2025-01-01' AND '2025-12-31';هام SQL operators وتشمل التعبيراتLIKE,في,BETWEEN,هو NULL,هو NOT NULL,EXISTS,ANY، وALL.
يدعم MySQL أيضًا المساواة الآمنة NULL operator<=>. يمكنه مقارنة القيم حتى عند استخدام NULL:
SELECT *
FROM users
WHERE deleted_at <=> NULL;في استعلامات التطبيق العادية،هو NULLعادة ما يكون أكثر وضوحا. ومع ذلك، فإن NULL الآمن operator مفيد في بعض سيناريوهات المقارنة والمزامنة.
كيف تعمل ميزات MySQL معًا
في التطبيقات الحقيقية، نادرًا ما يتم استخدام هذه الميزات بمعزل عن غيرها. قد يقوم استعلام التقرير بربط جداول متعددة وتجميع النتائج وتصفية القيم المجمعة باستخدام HAVING ومعالجة قيم NULL باستخدام COALESCE وتصنيف الصفوف باستخدام CASE.
المثال التالي يجمع عدة مفاهيم في تقرير عملي واحد:
SELECT
c.id,
c.name,
COALESCE(c.city, 'Unknown') AS city,
COUNT(o.id) AS orders_count,
SUM(CASE WHEN o.status = 'paid' THEN o.total ELSE 0 END) AS paid_total,
CASE
WHEN SUM(CASE WHEN o.status = 'paid' THEN o.total ELSE 0 END) >= 5000 THEN 'VIP'
WHEN COUNT(o.id) >= 5 THEN 'Regular'
ELSE 'New'
END AS customer_level
FROM customers AS c
LEFT JOIN orders AS o
ON c.id = o.customer_id
GROUP BY
c.id,
c.name,
c.city
HAVING paid_total > 0
ORDER BY paid_total DESC;يقوم هذا الاستعلام بإرجاع العملاء الذين لديهم نشاط طلب مدفوع، ويعرض مدينتهم بقيمة احتياطية، ويحسب طلباتهم، ويحسب الإيرادات المدفوعة، ويعين مستوى العميل. ويستخدم LEFT JOIN، GROUP BY، HAVING، COALESCE، CASE، COUNT ()، SUM ()، aliases، والطلب.
هذا هو نوع الاستعلام الذي يظهر في لوحات المعلومات وأنظمة إدارة علاقات العملاء وصفحات التحليلات ولوحات إدارة التجارة الإلكترونية والتقارير المالية.
الأداء وأفضل الممارسات
تعد ميزات SQL المتقدمة قوية، ولكن يجب كتابتها بعناية. يمكن أن يكون الاستعلام صحيحًا منطقيًا ولا يزال أداءه سيئًا إذا زاد حجم database.
تشمل الممارسات المهمة ما يلي:
استخدم indexes على أعمدة الربط، وأعمدة التصفية، والأعمدة المجمعة بشكل متكرر عندما يكون ذلك مناسبًا.
اكتب دائمًا شروطًا واضحة للصلات.
تجنب SELECT * في التقارير والاستعلامات المرتبطة إلا إذا كنت تحتاج حقًا إلى كل عمود.
استخدم UNION ALL بدلاً من UNION عندما لا تكون هناك حاجة إلى إزالة التكرارات.
استخدم WHERE قبل GROUP BY لتقليل عدد الصفوف التي يتم تجميعها.
استخدم HAVING فقط للشروط التي تعتمد على النتائج المجمعة.
اختبر استعلامات SELECT قبل استخدامها داخل INSERT SELECT.
استخدم aliases باستمرار لتحسين إمكانية القراءة.
استخدم EXPLAIN لفحص كيفية تخطيط MySQL لتنفيذ الاستعلامات المهمة.
تعد SQL القابلة للقراءة أيضًا مهارة احترافية. سيكون الاستعلام الذي تم تنسيقه بشكل جيد، ويستخدم aliases ذي معنى، ويفصل المنطق بشكل واضح، أسهل في تصحيح الأخطاء وتحسينه وصيانته.
الاستنتاج
تعتبر وصلات MySQL وميزات SQL المتقدمة ضرورية لبناء تطبيقات حقيقية تعتمد على database. تساعد INNER JOIN، وLEFT JOIN، وRIGHT JOIN، وCROSS JOIN، والصلات الذاتية على دمج البيانات ذات الصلة. يجمع UNION وUNION ALL النتائج من استعلامات SELECT المتعددة. GROUP BY وHAVING يجعلان إعداد التقارير وaggregation ممكنين.
تسمح EXISTS وANY وALL بمنطق استعلام فرعي أكثر تقدمًا. INSERT يساعد SELECT على نسخ البيانات وتحويلها بين الجداول. يضيف CASE مخرجات مشروطة. تعمل وظائف NULL على جعل القيم المفقودة أكثر أمانًا ووضوحًا. توفر الإجراءات المخزنة منطق الجانب database القابل لإعادة الاستخدام. تعمل التعليقات على تحسين قابلية الصيانة، وتشكل operators أساس التصفية والمقارنة والحساب.
لإتقان MySQL، تدرب على هذه المواضيع باستخدام جداول حقيقية وبيانات واقعية. ابدأ بالصلات البسيطة، ثم قم بإضافة التجميع والتصفية وتعبيرات CASE والاستعلامات الفرعية خطوة بخطوة. كلما فهمت كيفية عمل هذه الميزات معًا، أصبح من الأسهل كتابة SQL بشكل نظيف ودقيق وفعال للمشاريع الحقيقية.

