سلسلة sql للمحترفين البحث والتنقيب والترشيح في SQL


محمد الميداوي

تستعرض هذه المقالة بعض معاملات SQL المتخصصة في البحث والتنقيب وترشيح النتائج.

المعامل LIKE

مطابقة الأنماط المفتوحة Match open-ended pattern

يطابق حرف البدل ‎%‎ الموضوع في بداية أو نهاية السلسلة النصية (أو كليهما) 0 حرف أو أكثر قبل بداية أو بعد نهاية النمط المراد مطابقته.

يسمح استخدام "%' في الوسط بوجود 0 حرف أو أكثر بين جزأي النمط المُراد مُطابقته.

سنستخدم جدول الموظفين Employees التالي:

Id FName LName PhoneNumber ManagerId DepartmentId Salary Hire_date
1 John Johnson 2468101214 1 1 400 23-03-2005
2 Sophie Amudsen 2479100211 1 1 400 11-01-2010
3 Ronny Smith 2462544026 2 1 600 06-08-2015
4 Jon Sanchez 2454124602 1 1 400 23-03-2005
5 Hilde Knag 2468021911 2 1 800 01-01-2000

تطابق العبارة التالية جميع السجلات التي يحتوي حقل FName خاصتها على السلسلة النصية 'on':

SELECT * FROM Employees WHERE FName LIKE '%on%';

سنحصل على الخرج التالي:

Id FName LName PhoneNumber ManagerId DepartmentId Salary Hire_date
3 Ronny Smith 2462544026 2 1 600 06-08-2015
4 Jon Sanchez 2454124602 1 1 400 23-03-2005

يطابق التعبير التالي جميع السجلات التي يبدأ الحقل PhoneNumber خاصتها بالسلسلة النصية "246" في جدول الموظفين.

SELECT * FROM Employees WHERE PhoneNumber LIKE '246%';

سنحصل على الخرج التالي:

Id FName LName PhoneNumber ManagerId DepartmentId Salary Hire_date
1 John Johnson 2468101214 1 1 400 23-03-2005
3 Ronny Smith 2462544026 2 1 600 06-08-2015
5 Hilde Knag 2468021911 2 1 800 01-01-2000

تطابق العبارة التالية جميع السجلات التي ينتهي الحقل PhoneNumber خاصتها بالسلسلة النصية "11" في جدول الموظفين.

SELECT * FROM Employees WHERE PhoneNumber LIKE '%11'
Id FName LName PhoneNumber ManagerId DepartmentId Salary Hire_date
2 Sophie Amudsen 2479100211 1 1 400 11-01-2010
5 Hilde Knag 2468021911 2 1 800 01-01-2000

يطابق التعبير التالي جميع السجلات التي يساوي الحرف الثالث من حقل Fname خاصتها 'n' في جدول الموظفين.

SELECT * FROM Employees WHERE FName LIKE '__n%';

(استخدمنا شرطتين سفليتين قبل 'n' لتخطي أول حرفين)

Id FName LName PhoneNumber ManagerId DepartmentId Salary Hire_date
3 Ronny Smith 2462544026 2 1 600 06-08-2015
4 Jon Sanchez 2454124602 1 1 400 23-03-2005

مطابقة محرف واحد

يمكن استخدام أحرف البدل وعلامة النسبة المئوية (%) والشرطة السفلية (_) لتوسيع أنماط الاختيار في SQL.

يمكن استخدام المحرف ‎_‎ (الشرطة السفلية) كحرف بدل يمثل حرفًا منفردًا.

يبحث النمط التالي عن جميع الموظفين الذين يتألف الحقل Fname خاصتهم من 3 حروف، ويبدأ بالحرف "j" وينتهي بـ "n".

SELECT * FROM Employees WHERE FName LIKE 'j_n'

يمكن استخدام المحرف ‎_‎ أكثر من مرة بحيث يتصرف كبطاقة بدل (wild card) لمطابقة أنماط معينة.

على سبيل المثال، يُطابق النمط أعلاه السلاسل النصية التالية: jon و jan و jen. بيْد أنّه لا يُطابق الأسماء التالية: jn و john و jordan و justin و jason و julian و jillian و joann، لأنّ الشرطة السفلية التي استخدمناها في الاستعلام تتخطى حرفًا واحدًا فقط، لذلك لن تُقبل إلا الحقول المؤلفة من 3 أحرف.

يُطابق النمط التالي السلاسل النصية التالية: LaSt و LoSt و HaLt:

SELECT * FROM Employees WHERE FName LIKE '_A_T'

العبارة ESCAPE في الاستعلام LIKE

يمكن إجراء بحث نصي في العبارة ‎LIKE‎ على النحو التالي:

SELECT *
FROM T_Whatever
WHERE SomeField LIKE CONCAT('%', @in_SearchText, '%')

ستحدث مشكلة إذا أدخل شخص ما نصُّا من قبيل "50%" أو "a_b" (بصرف النظر عن حقيقة أنه يُفضل البحث عن النص الكامل بدل استخدام ‎LIKE‎). يمكن حل هذه المشكلة باستخدام عبارة ‎LIKE‎:

SELECT *
FROM T_Whatever
WHERE SomeField LIKE CONCAT('%', @in_SearchText, '%') ESCAPE '\'

هذا يعني أنّ ‎\‎ ستُعامل كحرف التهريب ESCAPE. أي أنّه يمكنك الآن إضافة ‎\‎ إلى كل حرف في السلسلة النصية التي تبحث عنها، وستكون النتائج صحيحة، حتى لو أدخل المستخدم محارف خاصة مثل ‎%‎ أو ‎_‎.

إليك المثال التالي:

string stringToSearch = "abc_def 50%";
string newString = "";
foreach(char c in stringToSearch)
     newString += @"\" + c;

sqlCmd.Parameters.Add("@in_SearchText", newString);
// sqlCmd.Parameters.Add("@in_SearchText", stringToSearch); بدلا من

ملاحظة: وضعنا الخوارزمية أعلاه للتوضيح وحسب، ولن تعمل في حال احتوت السلسلة النصية على رسمة (grapheme) مؤلفة من عدّة أحرف (مثل رموز utf-8). مثلًا، في السلسلة النصية ‎string stringToSearch = "Les Mise\u0301rables";‎، ستحتاج إلى فعل ذلك لكل رسمة، وليس لكل حرف. عليك ألا تستخدم الخوارزمية أعلاه إذا كنت تتعامل مع لغات آسيوية أو شرق آسيوية أو جنوب آسيوية.

البحث عن مجموعة من المحارف

تطابق العبارة التالية جميع السجلات التي يبدأ حقل FName خاصتها بحرف محصور (أبجديا) بين A و F في جدول الموظفين.

SELECT * FROM Employees WHERE FName LIKE '[A-F]%'

مطابقة نطاق أو مجموعة

يمكن مطابقة حرف واحد داخل نطاق محدد (على سبيل المثال: ‎[a-f]‎) أو مجموعة (على سبيل المثال: ‎[abcdef]‎).

يطابق نمط النطاق التالي السلسلة النصية gary، ولكن ليس mary:

SELECT * FROM Employees WHERE FName LIKE '[a-g]ary'

يُطابق نمط المجموعة التالي mary ولكن ليس gary:

SELECT * FROM Employees WHERE Fname LIKE '[lmnop]ary'

يمكن أيضًا عكس أو نفي النطاق أو المجموعة بوضع العلامة ‎^‎ قبل النطاق أو المجموعة، فلن يتطابق نمط النطاق التالي مع gary، ولكنه سيتطابق مع mary:

SELECT * FROM Employees WHERE FName LIKE '[^a-g]ary'

لن يتطابق نمط المجموعة التالي مع mary ولكن سيتطابق مع gary:

SELECT * FROM Employees WHERE Fname LIKE '[^lmnop]ary'

أحرف البدل Wildcard characters

يمكن استخدام أحرف البدل مع المعامل LIKE. تُستخدم أحرف البدل في SQL للبحث عن البيانات داخل جدول معيّن. وهناك أربعة منها، وهي كالتالي:

  • % - بديل عن صفر حرف أو أكثر
--   "Lo" اختيار جميع العملاء الذين يقطنون مدينة تبدأ بـ 
 SELECT * FROM Customers
 WHERE City LIKE 'Lo%';

-- "es" اختيار جميع العملاء الذين يقطنون مدينة تحتوي 
 SELECT * FROM Customers
 WHERE City LIKE '%es%';
  • _ - بديل عن حرف واحد
-- erlin  اختيار جميع العملاء الذين يقطنون مدينة تبدأ بحرف معين، متبوعا بـ 
SELECT * FROM Customers
WHERE City LIKE '_erlin';
  • [charlist] - مجموعات ونطاقات مؤلفة من الحروف المُراد مُطابقتها
-- "a" أو "d" أو "l" اختيار جميع العملاء الذين يقطنون مدينة تبدأ بـ 
SELECT * FROM Customers
WHERE City LIKE '[adl]%';
-- "a" أو "d" أو "l" اختيار جميع العملاء الذين يقطنون مدينة تبدأ بـ 
SELECT * FROM Customers
WHERE City LIKE '[a-c]%';
  • [‎^ charlist] - تطابق الحروف غير الموجودة داخل القوسين المربعين
-- "a" أو "d" أو "l" اختيار جميع العملاء الذين يقطنون مدينة لا تبدأ بـ 
SELECT * FROM Customers
WHERE City LIKE '[^apl]%';
or
SELECT * FROM Customers
WHERE City NOT LIKE '[apl]%' and city like '_%';

التحقق من الانتماء عبر IN

يمكن استخدام العبارة IN للتحقق من إنتماء قيمة إلى مجموعة معينة.

تعيد الشيفرة التالية السجلات التي ينتمي مُعرّفها ‎id‎ إلى مجموعة معينة من القيم ((1,8,3)):

select *
from products
where id in (1,8,3)

يكافئ الاستعلام أعلاه:

select *
from products
where id = 1
 or id = 8
 or id = 3

يمكن استخدام IN مع استعلام فرعي على النحو التالي:

SELECT *
FROM customers
WHERE id IN (
 SELECT DISTINCT customer_id
 FROM orders
);

ستعيد الشيفرة أعلاه جميع العملاء الذين لديهم طلبات في النظام.

ترشيح النتائج باستخدام WHERE و HAVING

استخدم BETWEEN لترشيح النتائج

تستخدم الأمثلة التالية قاعدتي البيانات Sales و Customers.

تذكر أنّ المعامل BETWEEN تضميني (inclusive):

استخدام المعامل BETWEEN مع الأعداد

يعيد الاستعلام التالي جميع سجلات ‎ItemSales‎ التي ينحصر حقل الكمية quantity خاصتها بين 10 و 17.

SELECT * From ItemSales
WHERE Quantity BETWEEN 10 AND 17

سنحصل على النتائج التالية:

Id SaleDate ItemId Quantity Price
1 2013-07-01 100 10 34.5
4 2013-07-23 100 15 34.5
5 2013-07-24 145 10 34.5

استخدام المعامل BETWEEN مع قيم التاريخ

يعيد الاستعلام التالي كافة سجلات ‎ItemSales‎ التي ينحصر حقل ‎SaleDate‎ خاصتها بين التاريخين 11 يوليو 2013 و 24 مايو 2013.

SELECT * From ItemSales
WHERE SaleDate BETWEEN '2013-07-11' AND '2013-05-24'

هذا هو الخرج المتوقع:

Id SaleDate ItemId Quantity Price
3 2013-07-11 100 20 34.5
4 2013-07-23 100 15 34.5
5 2013-07-24 145 10 34.5

عند موازنة قيم الوقت (datetime) بدلًا من قيم التاريخ (dates)، قد تحتاج إلى تحويل قيم الوقت إلى قيم التاريخ، أو إضافة أو طرح 24 ساعة للحصول على النتيجة المتوقعة.

استخدام المعامل BETWEEN مع القيم النصية

يعيد الاستعلام التالي كافة العملاء الذين تنحصر أسماؤهم (أبجديًا) بين الحرفين 'D' و 'L'. في هذه الحالة، سيُعاد العميلان ذوي الرقمين 1 و 3. أما العميل رقم 2 ، الذي يبدأ اسمه بـالحرف "M"، فلن يُعاد:

SELECT Id, FName, LName FROM Customers
WHERE LName BETWEEN 'D' AND 'L';

هذا مثال حي

الخرج:

Id FName LName
1 William Jones
3 Richard Davis

استخدم HAVING مع الدوال التجميعية

على خلاف العبارة ‎WHERE‎ ، يمكن استخدام ‎HAVING‎ مع الدوال التجميعية.

الدوال التجميعية (aggregate functions) هي دوال تأخذ القيم الموجودة في في عدة صفوف كمُدخلات (بناء على شروط محددة) وتعيد قيمة معينة. هذه بعض الدوال التجميعية: ‎COUNT()‎ و ‎SUM()‎ و ‎MIN()‎ و ‎MAX()‎.

يستخدم هذا المثال الجدول Car من الفصل الأول.

SELECT CustomerId, COUNT(Id) AS [Number of Cars]
FROM Cars
GROUP BY CustomerId
HAVING COUNT(Id) > 1

يعيد الاستعلام أعلاه ‎CustomerId‎ وعدد السيارات ‎Number of Cars‎ لأيّ عميل لديه أكثر من سيارة واحدة. في هذا المثال، العميل الوحيد الذي لديه أكثر من سيارة واحدة هو العميل رقم 1.

هذا هو الخرج:

CustomerId Number of Cars
1 2

استخدام WHERE مع القيم NULL / NOT NULL

يعيد المثال التالي جميع سجلات الموظفين (Employee) التي تتساوى قيمة العمود ‎ManagerId‎ خاصتهم مع القيمة المعدومة ‎NULL‎.

SELECT *
FROM Employees
WHERE ManagerId IS NULL

النتيجة:

Id    FName    LName    PhoneNumber    ManagerId    DepartmentId
1     James     Smith      1234567890        NULL           1

يعيد المثال التالي جميع سجلات الموظفين التي لا تساوي قيمة العمود ‎ManagerId‎ خاصتهم القيمة ‎NULL‎.

SELECT *
FROM Employees
WHERE ManagerId IS NOT NULL

ستكون النتيجة كما يلي:

Id    FName       LName     PhoneNumber    ManagerId    DepartmentId
2     John           Johnson    2468101214      1                    1
3     Michael       Williams   1357911131       1                    2
4     Johnathon   Smith       1212121212       2                   1

ملاحظة: لن يعيد الاستعلام أعلاه أيّ نتائج في حال غيّرت صياغة العبارة WHERE إلى ‎WHERE ManagerId = NULL‎ أو ‎WHERE‎ ‎ManagerId‎ <> NULL.

معامل التساوي

تعيد الشيفرة التالية كل صفوف الجدول ‎Employees‎.

SELECT * FROM Employees

الخرج:

Id   FName     LName    PhoneNumber   ManagerId   DepartmentId    Salary  Hire_date CreatedDate   ModifiedDate
1    James     Smith        1234567890      NULL          1                        1000     01-01-2002  01-01-2002  01-01-2002
2    John       Johnson     2468101214      1                1                        400       23-03-2005   23-03-2005  01-01-2002
3    Michael   Williams    1357911131      1                  2                        600      12-05-2009   12-05-2009  NULL
4    Johnathon Smith      1212121212      2                 1                        500       24-07-2016   24-07-2016  01-01-2002

يتيح لك استخدام ‎WHERE‎ في نهاية العبارة ‎SELECT‎ ترشيح الصفوف المُعادة وفق شرط معين. إن أردت مثلًا اشتراط التطابق التام مع قيمة معينة، فاستخدم علامة التساوي ‎=‎:

SELECT * FROM Employees WHERE DepartmentId = 1

لن يعيد الاستعلام أعلاه إلا الصفوف التي يساوي الحقل ‎DepartmentId‎ خاصتها القيمة ‎1‎:

Id   FName     LName    PhoneNumber   ManagerId   DepartmentId    Salary  Hire_date       CreatedDate   ModifiedDate
1    James       Smith      1234567890       NULL          1                       1000      01-01-2002    01-01-2002    01-01-2002
2    John          Johnson  2468101214       1                 1                       400        23-03-2005    23-03-2005    01-01-2002
4    Johnathon Smith       1212121212       2                 1                       500        24-07-2016    24-07-2016     01-01-2002

لنفترض أنّ متجرًا للألعاب لديه فئة من الألعاب يقل سعرها عن 10 دولارات. يعيد الاستعلام التالي هذه الفئة من الألعاب:

SELECT *
FROM Items
WHERE Price < 10

المعاملان المنطقيان AND و OR

يمكنك الجمع بين عدة معاملات معًا لإنشاء شروط ‎WHERE‎ أكثر تعقيدًا.

تستخدم الأمثلة التالية الجدول ‎Employees‎ التالي:

Id   FName     LName    PhoneNumber   ManagerId   DepartmentId    Salary    Hire_date       CreatedDate   ModifiedDate
1    James       Smith      1234567890      NULL           1                       1000        01-01-2002    01-01-2002    01-01-2002
2    John         Johnson   2468101214      1                  1                       400         23-03-2005    23-03-2005     01-01-2002
3    Michael     Williams  1357911131       1                   2                       600         12-05-2009    12-05-2009    NULL
4    Johnathon  Smith     1212121212       2                   1                       500         24-07-2016    24-07-2016    01-01-2002

إليك الاستعلام التالي:

SELECT * FROM Employees WHERE DepartmentId = 1 AND ManagerId = 1

سينتج الخرج التالي:

Id   FName     LName    PhoneNumber   ManagerId   DepartmentId    Salary  Hire_date        CreatedDate   ModifiedDate
2    John        Johnson   2468101214      1                   1                       400         23-03-2005    23-03-2005    01-01-2002

وهذا استعلام آخر يستخدم المعامل المنطقي OR:

SELECT * FROM Employees WHERE DepartmentId = 2 OR ManagerId = 2

سينتج الخرج التالي:

Id   FName     LName    PhoneNumber   ManagerId   DepartmentId    Salary  Hire_date       CreatedDate   ModifiedDate
3    Michael     Williams   1357911131      1                  2                       600         12-05-2009    12-05-2009   NULL
4    Johnathon Smith      1212121212      2                  1                       500         24-07-2016     24-07-2016   01-01-2002

استخدم IN لإعادة الصفوف التي تنتمي قيمها إلى قائمة معينة

يستخدم هذا المثال الجدول "Car".

SELECT *
FROM Cars
WHERE TotalCost IN (100, 200, 300)

سيعيد هذا الاستعلام السيارة رقم 2، والتي تبلغ تكلفتها 200، والسيّارة رقم 3، والتي تساوي تكلفتها 100. لاحظ أنّ الاستعلام أعلاه يكافئ استخدام ‎OR‎ عدة مرّات كما هو موضّح في المثال التالي:

SELECT *
FROM Cars
WHERE TotalCost = 100 OR TotalCost = 200 OR TotalCost = 300

استخدم LIKE للبحث عن السلاسل النصية

يستخدم المثال التالي الجدول Car:

SELECT *
FROM Employees
WHERE FName LIKE 'John'

لن يعيد هذا الاستعلام إلا الموظف رقم 1، والذي يتطابق اسمه الأول مع السلسلة النصية "John".

SELECT *
FROM Employees
WHERE FName like 'John%'

يمكنك البحث عن سلسلة نصية فرعية عبر إضافة الرمز ‎%‎:

  • John%‎‎ - تعيد أيّ موظف يبدأ اسمه بـ "John" ، متبوعًا بأي عدد من الأحرف
  • ‎‎%John‎‎ - تعيد أيّ موظف ينتهي اسمه بـ "John" ، يعقبه أي عدد من الأحرف
  • ‎%‎John‎%‎ - تعيد أيّ موظف يتضمّن اسمه السلسلة النصية "John"

في المثال أعلاه، سيعيد الاستعلام الموظفَ رقم 2، والذي يحمل الاسم "John"، وكذلك الموظف رقم 4، والذي يحمل الاسم "Johnathon".

Where EXISTS

في المثال التالي، تختار العبارة WHERE EXISTS سجلّات ‎TableName‎ التي تطابق سجلاتٍ في الجدول ‎TableName1‎.

SELECT * FROM TableName t WHERE EXISTS (
 SELECT 1 FROM TableName1 t1 where t.Id = t1.Id)

استخدام HAVING للتحقق من عدة شروط

إليك جدول الطلبات التالي:

CustomerId ProductId Quantity Price
1 2 5 100
1 3 2 200
1 4 1 500
2 1 4 50
3 5 6 700

للحصول على العملاء الذين طلبوا المنتَجَين ذوي المُعرّف 2 و 3، يمكن استخدام العبارة HAVING:

 select customerId
 from orders
 where productID in (2,3)
 group by customerId
 having count(distinct productID) = 2

الخرج الناتج:

customerId
1

لن يختار الاستعلام إلا السجلات ذات معرّفات المنتجات المحددة، والتي تحقق شرط HAVING، أي وجود معرّفين اثنين للمنتجات (productIds)، وليس معرّفًا واحدًا فقط.

هذه صياغة أخرى:

 select customerId
 from orders
 group by customerId
 having sum(case when productID = 2 then 1 else 0 end) > 0
     and sum(case when productID = 3 then 1 else 0 end) > 0

لن يختار هذا الاستعلام إلا المجموعات التي لها سجل واحد على الأقل يساوي معرّف منتجه (productID) القيمة 2، وسجل واحد على الأقل يساوي معرّف منتجه 3.

ترقيم الصفحات Pagination

يمكن وضع حدّ لعدد النتائج المُعادة في استعلام معين، لكنّ الصياغة تختلف بحسب النظام المُستخدم:

  • في إصدار SQL القياسي ISO / ANSI:
SELECT * FROM TableName FETCH FIRST 20 ROWS ONLY;
  • MySQL و PostgreSQL و SQLite:
SELECT * FROM TableName LIMIT 20;
  • Oracle :
SELECT Id,
   Col1
FROM (SELECT Id,
           Col1,
 row_number() over (order by Id) RowNumber
 FROM TableName)
WHERE RowNumber <= 20
  • SQL Server:
SELECT TOP 20 *
FROM dbo.[Sale]

قد ترغب أحيانًا في تخطّي عدد من نتائج الاستعلام وتأخذ النتائج الموالية لها، يمكنك ذلك عبر الصياغة التالية:

  • ISO / ANSI SQL:
SELECT Id, Col1
FROM TableName
ORDER BY Id
OFFSET 20 ROWS FETCH NEXT 20 ROWS ONLY;
  • MySQL:
SELECT * FROM TableName LIMIT 20, 20; -- offset, limit
  • Oracle و SQL Server:
SELECT Id,
   Col1
 FROM (SELECT Id,
           Col1,
 row_number() over (order by Id) RowNumber
 FROM TableName)
WHERE RowNumber BETWEEN 21 AND 40
  • PostgreSQL و SQLite:
SELECT * FROM TableName LIMIT 20 OFFSET 20;

يمكنك كذلك تخطي بعض الصفوف من نتائج الاستعلام على النحو التالي:

  • ISO / ANSI SQL:
SELECT Id, Col1
FROM TableName
ORDER BY Id
OFFSET 20 ROWS
  • MySQL:
SELECT * FROM TableName LIMIT 20, 42424242424242;
-- تخطي 20 صفا، بالنسبة لعدد الصفوف المأخوذة، استخدم عددا كبيرا يتجاوز عدد الصفوف في الجدول
  • Oracle:
SELECT Id,
   Col1
FROM (SELECT Id,
           Col1,
 row_number() over (order by Id) RowNumber
 FROM TableName)
WHERE RowNumber > 20
  • PostgreSQL:
SELECT * FROM TableName OFFSET 20;
  • SQLite:
SELECT * FROM TableName LIMIT -1 OFFSET 20;

EXCEPT

يمكنك استثناء مجموعة من البيانات عبر استخدام الكلمة المفتاحية EXCEPT.

إليك المثال التالي:

-- ينبغي أن تكون مجموعات البيانات متماثلة
SELECT 'Data1' as 'Column' UNION ALL
SELECT 'Data2' as 'Column' UNION ALL
SELECT 'Data3' as 'Column' UNION ALL
SELECT 'Data4' as 'Column' UNION ALL
SELECT 'Data5' as 'Column'
EXCEPT
SELECT 'Data3' as 'Column'
-- ==>  Data1 و Data2 و Data4 و Data5

EXPLAIN و DESCRIBE

استعمال EXPLAIN في استعلامات الاختيار

عند وضع ‎Explain‎ قُبالة استعلام ‎select‎، سيعرض محرّك قاعدة البيانات بعض البيانات التي توضّح كيفية تنفيذ الاستعلام. يمكنك استخدام هذه البيانات لفهم الشيفرة ومن ثَمَّ تحسينها، مثلًا، لو لاحظت أنّ الاستعلام لا يستخدم فهرسًا، فيمكنك تحسين استعلامك عن طريق إضافة فهرس.

إليك الاستعلام التالي:

explain select * from user join data on user.test = data.fk_user;

سنحصل على الخرج التالي:

id  select_type  table   type     possible_keys  key       key_len ref          rows  Extra
1   SIMPLE       user    index   test                   test      5            (null)       1      Using where; Using index
1   SIMPLE       data    ref       fk_user             fk_user 5           user.tes t 1     (null)

يحدد العمود ‎type‎ ما إذا كان الاستعلام يستخدم الفهرس أم لا. وفي العمود ‎possible_keys‎، سترى ما إذا كان بالإمكان تنفيذ الاستعلام بواسطة فهارس أخرى إن لم يتوافر الفهرس. يعرض ‎key‎ الفهرس المستخدم، فيما يعرض العمود ‎key_len‎ حجم عنصر من الفهرس (بالبايتات bytes)، وكلما انخفضت هذه القيمة، زاد عدد عناصر الفهرس التي يمكن تخزينها في مساحة معينة من الذاكرة، وهو ما يسرّع معالجتها. يعرض العمود ‎rows‎ العدد المتوقع للصفوف التي يحتاج الاستعلام إلى جردها، كلما كان هذا العدد أصغر، كان الأداء أفضل.

DESCRIBE tablename

‎DESCRIBE‎ و EXPLAIN متماثلتان، بيد أنّ ‎DESCRIBE‎ تعيد معلومات تعريفية لأعمدة الجدول tablename:

DESCRIBE tablename;

النتيجة:

COLUMN_NAME     COLUMN_TYPE     IS_NULLABLE     COLUMN_KEY     COLUMN_DEFAULT    EXTRA
id                              int(11)                       NO                      PRI                         0                                 auto_increment
test                           varchar(255)            YES                                                     (null) 

عُرِضت أسماء الأعمدة متبوعة بنوعها، إضافة إلى توضيح ما إذا كان من الممكن استخدام ‎null‎ في العمود، وما إذا كان العمود يستخدم فهرسًا. تُعرض أيضًا القيمة الافتراضية للعمود، وما إذا كان الجدول ينطوي على أّي سلوك خاص، مثل ‎auto_increment‎.

العبارة EXISTS

إليك جدول العملاء التالي:

Id FirstName LastName
1 Ozgur Ozturk
2 Youssef Medi
3 Henry Tai

وهذا جدول آخر للطلبيّات:

Id CustomerId Amount
1 2 123.50
2 3 14.80

تعيد هذه الشيفرة جميع العملاء الذين قدموا طلبية واحدة على الأقل:

SELECT * FROM Customer WHERE EXISTS (
 SELECT * FROM Order WHERE Order.CustomerId=Customer.Id
)

النتيجة المتوقعة:

Id FirstName LastName
2 Youssef Medi
3 Henry Tai

يعيد الاستعلام التالي جميع العملاء الذين لم يقدّمو أيّ طلبية:

SELECT * FROM Customer WHERE NOT EXISTS (
 SELECT * FROM Order WHERE Order.CustomerId = Customer.Id
)

النتيجة المتوقّعة:

Id FirstName LastName
1 Ozgur Ozturk

تُستخدم ‎EXISTS‎ و IN و ‎JOIN‎ أحيانًا للحصول على النتائج نفسها، بيْد أنّ هناك اختلافات في كيفية عملها:

  • تُستخدم ‎EXISTS‎ للتحقق من وجود قيمة في جدول آخر.
  • تُستخدم ‎IN‎ للحصول على قائمة ثابتة.
  • تُستخدم ‎JOIN‎ لاسترجاع البيانات من جداول أخرى.

ترجمة -وبتصرّف- للفصول من 11 إلى 17 من الكتاب SQL Notes for Professionals





تفاعل الأعضاء


لا توجد أيّة تعليقات بعد



يجب أن تكون عضوًا لدينا لتتمكّن من التعليق

انشاء حساب جديد

يستغرق التسجيل بضع ثوان فقط


سجّل حسابًا جديدًا

تسجيل الدخول

تملك حسابا مسجّلا بالفعل؟


سجّل دخولك الآن