قد تضطر في بعض الأحيان إلى التعامل مع قيم تمثل تواريخ أو أوقات محددة لدى العمل مع قواعد البيانات العلاقية ولغة الاستعلام البنيوية SQL. فعلى سبيل المثال، قد ترغب في حساب إجمالي الساعات المُستغرقة في أداء نشاطٍ ما، أو قد تحتاج إلى مُعالجة قيم التواريخ أو الأوقات باستخدام المعاملات الرياضية ودوال التجميع لحساب مجموعها أو متوسطها.
ستتعلم في هذا المقال كيفية استخدام التواريخ والأوقات في SQL. إذ ستبدأ بإجراء العمليات الحسابية واستخدام دوال متنوعة مع التواريخ والأوقات باستخدام تعليمة SELECT
وحدها. لتتدرب بعد ذلك على تنفيذ استعلامات على بياناتٍ نموذجية تجريبية، وستتعلم كيفية استخدام دالة CAST
لجعل النتائج أيسر للقراءة.
مستلزمات العمل
لمتابعة الخطوات في هذا المقال، ستحتاج إلى:
-
خادم عامل على توزيعة أوبنتو، مع مستخدم ذو صلاحيات مسؤول من نوع
sudo
مختلف عن المستخدم الجذر، وجدار حماية مُفعّل، كما هو موضح المقال كيفية تثبيت توزيعة أوبنتو من لينكس بأبسط طريقة. - MySQL مثبتة ومؤمنة على الخادم، كما هو موضح في المقال كيفية تثبيت MySQL على أوبونتو. وقد نفذنا خطوات هذا المقال باستخدام مستخدم MySQL مختلف عن المستخدم الجذر، مُنشأ وفق الطريقة الموضحة في الخطوة 3 من هذا المقال.
ملاحظة: تجدر الإشارة إلى أنّ الكثير من أنظمة إدارة قواعد البيانات العلاقية لها تقديماتها الفريدة من لغة SQL. فبالرغم من كون الأوامر المُقدمة في هذا المقال ستعمل مع معظم هذه الأنظمة، ولكن قد تجد بعض الاختلافات في الصيغة أو الناتج عند تنفيذها على أنظمة مختلفة عن MySQL.
وبالعودة إلى مستلزمات العمل، ستحتاج أيضًا إلى قاعدة بيانات وجدول مُحمّل ببعض البيانات التجريبية النموذجية لتتمكن من التدرب على الأمثلة حول كيفية استخدام التاريخ والوقت في هذا المقال. لذا ننصحك بمتابعة القسم القادم الاتصال بـ MySQL وإعداد قاعدة بيانات تجريبية نموذجية للمزيد من التفاصيل حول كيفية إعداد قاعدة بيانات وجدول لاستخدامهما في الأمثلة خلال هذا المقال.
الاتصال بـ MySQL وإعداد قاعدة بيانات تجريبية نموذجية
إذا كان نظام قاعدة بيانات SQL الخاص بك يعمل على خادم عن بُعد، اتصل بالخادم مُستخدمًا بروتوكول SSH من جهازك المحلي على النحو التالي:
$ ssh ssh user@your_server_ip
ثم افتح واجهة سطر الأوامر في خادم MySQL، مُستبدلًا user
باسم حساب مستخدم MySQL الخاص بك:
$ mysql -u user -p
أنشئ قاعدة بيانات باسم datetimeDB
:
mysql> CREATE DATABASE datetimeDB;
وبمجرّد إنشاء قاعدة البيانات بنجاح ستحصل على خرجٍ كالتالي:
الخرج Query OK, 1 row affected (0.01 sec)
ولاختيار قاعدة البيانات datetimeDB
، نفّذ تعليمة USE
التالية:
mysql> USE datetimeDB;
الخرج Database changed
الآن وبعد اختيار قاعدة البيانات datetimeDB
، لننشئ جدولًا ضمنها.
كمثال في مقالنا هذا، سننشئ جدولًا يُسجّل نتائج اثنين من العدائين في مختلف السباقات التي شاركا بها على مدار عام. سيضم الجدول الأعمدة السبعة التالية:
-
race_id
: يُمثّل قيمًا من نمط بيانات الأعداد الصحيحةint
وسيكون المفتاح الأساسي للجدول، ما يعني أن كل قيمة في هذا العمود ستلعب دور المعرّف الفريد لسجلها. -
runner_name
: مُخصص لأسماء هذين العدّائين وهما في مثالنا أحمد ومحمد وذلك باستخدام نمط البياناتvarchar
بحد أقصى 30 محرفًا. -
race_name
: يُخزّن أسماء السباقات باستخدام نمط البياناتvarchar
بحد أقصى 20 محرفًا. -
start_day
: لتسجيل تاريخ السباق باليوم والشهر والسنة باستخدام نمط البياناتDATE
. إذ يتبع نمط البيانات هذا الصيغة القياسية التالية: أربعة أرقام للسنة، وحد أقصى من رقمين لكل من الشهر واليوم (YYYY-MM-DD
). -
start_time
: يُمثل وقت بداية السباق باستخدام نمط بياناتTIME
بالساعات والدقائق والثواني (HH:MM:SS
). ويستخدم نمط البيانات هذا الوقت بصيغة 24 ساعة، أي15:00
على سبيل المثال للتعبير عن الساعة 3:00 مساءً. -
total_miles
: يعرض المسافة الإجمالية لكل سباق باستخدام نمط بياناتdecimal
، وذلك نظرًا لأن العديد من المسافات الإجمالية للسباقات ليست بأرقامٍ صحيحة. ويُمكّننا نمط البياناتdecimal
من تمثيل المسافات بدقة تصل إلى ثلاثة أرقام ككل، منها رقم واحد إلى يمين الفاصلة العشرية، أي بدقة تصل إلى عُشر الميل. -
end_time
: يُسجّل وقت انتهاء كل عدّاء من السباق باستخدام نمط بياناتTIMESTAMP
، الذي يدمج التاريخ والوقت ضمن تنسيق واحد يجمع بين صيغتيDATE
وTIME
مُشتملًا على السنة والشهر واليوم متبوعًا بالساعة والدقيقة والثانية، وهو يعتمد في ذلك على الصيغة
القياسية (YYYY-MM-DD HH:MM:SS) لتقديم توقيت دقيق للحظة انتهاء السباق.
ولإنشاء هذا الجدول، لننفّذ الأمر CREATE TABLE
التالي:
mysql> CREATE TABLE race_results ( mysql> race_id int, mysql> runner_name varchar(30), mysql> race_name varchar(20), mysql> start_day DATE, mysql> start_time TIME, mysql> total_miles decimal(3, 1), mysql> end_time TIMESTAMP, mysql> PRIMARY KEY (race_id) mysql> );
ثم املأ هذا الجدول الفارغ ببعض البيانات التجريبية النموذجية:
mysql> INSERT INTO race_results mysql> (race_id, runner_name, race_name, start_day, start_time, total_miles, end_time) mysql> VALUES mysql> (1, 'Ahmad', '1600_meters', '2022-09-18', '7:00:00', 1.0, '2022-09-18 7:06:30'), mysql> (2, 'Ahmad', '5K', '2022-10-19', '11:00:00', 3.1, '2022-10-19 11:22:31'), mysql> (3, 'Ahmad', '10K', '2022-11-20', '10:00:00', 6.2, '2022-11-20 10:38:05'), mysql> (4, 'Ahmad', 'half_marathon', '2022-12-21', '6:00:00', 13.1, '2022-12-21 07:39:04'), mysql> (5, 'Ahmad', 'full_marathon', '2023-01-22', '8:00:00', 26.2, '2023-01-22 11:23:10'), mysql> (6, 'Mohammad', '1600_meters', '2022-09-18', '7:00:00', 1.0, '2022-09-18 7:07:15'), mysql> (7, 'Mohammad', '5K', '2022-10-19', '11:00:00', 3.1, '2022-10-19 11:30:50'), mysql> (8, 'Mohammad', '10K', '2022-11-20', '10:00:00', 6.2, '2022-11-20 11:10:17'), mysql> (9, 'Mohammad', 'half_marathon', '2022-12-21', '6:00:00', 13.1, '2022-12-21 08:11:57'), mysql> (10, 'Mohammad', 'full_marathon', '2023-01-22', '8:00:00', 26.2, '2023-01-22 12:02:10');
الخرج Query OK, 10 rows affected (0.00 sec) Records: 10 Duplicates: 0 Warnings: 0
وبمجرّد إدخالك للبيانات تغدو مستعدًا لبدء التدرّب على استخدام بعض العمليات الحسابية والدوال مع التواريخ في SQL.
استخدام العمليات الحسابية مع التواريخ والأوقات
من الممكن معالجة قيم التواريخ والأوقات في SQL باستخدام التعابير الرياضية، ولن تحتاج سوى إلى العامل الرياضي والقيم المطلوب حسابها.
كمثال، لو أردنا تحديد تاريخ يأتي بعد عدد محدد من الأيام من تاريخٍ آخر. يأخذ الاستعلام التالي قيمة تاريخ معينة (2022-10-05
) ويضيف إليها 17، لإعادة قيمة التاريخ الذي يأتي بعد سبعة عشر يومًا من التاريخ المحدد في الاستعلام. وتجدر الملاحظة إلى أننا حددنا 2022-10-05
هنا كقيمة من نوع DATE
لضمان عدم تفسير نظام إدارة قاعدة البيانات لها كنص أو أي نوع بيانات آخر:
mysql> SELECT DATE '2022-10-05' + 17 AS new_date;
الخرج +----------+ | new_date | +----------+ | 20221022 | +----------+ 1 row in set (0.01 sec)
نلاحظ من هذا الخرج أنّ اليوم الذي يأتي بعد سبعة عشر يومًا من تاريخ 2022-10-05
هو 2022-10-22
، أو 22 أكتوبر 2022.
كمثال آخر، بفرض أننا نريد حساب إجمالي الساعات بين وقتين مختلفين من خلال طرحهما من بعضهما البعض. افترضنا في الاستعلام التالي أنّ 11:00
هو الوقت الأول و3:00
هو الوقت الثاني. ولا بدّ في هذه الحالة من تحديد أن كلاهما من نمط البيانات TIME
للحصول على الفرق بالساعات:
mysql> SELECT TIME '11:00' - TIME '3:00' AS time_diff;
الخرج +-----------+ | time_diff | +-----------+ | 80000 | +-----------+ 1 row in set (0.00 sec)
يُظهر هذا الخرج أن الفارق بين الساعة 11:00
والساعة 3:00
هو 80000، أو 8 ساعات.
الآن سنطبّق استعلامات على بياناتنا النموذجية بهدف التدرّب على كيفية استخدام العمليات الحسابية على معلومات التاريخ والوقت. بالنسبة للاستعلام الأول، سنحسب الزمن الكلي الذي استغرقه العداءان لإنهاء كل سباق من خلال طرح زمن الانتهاء end_time
من زمن البدء start_time
، على النحو التالي:
mysql> SELECT runner_name, race_name, end_time - start_time mysql> AS total_time mysql> FROM race_results;
الخرج +-------------+---------------+----------------+ | runner_name | race_name | total_time | +-------------+---------------+----------------+ | Ahmad | 1600_meters | 20220918000630 | | Ahmad | 5K | 20221019002231 | | Ahmad | 10K | 20221120003805 | | Ahmad | half_marathon | 20221221013904 | | Ahmad | full_marathon | 20230122032310 | | Mohammad | 1600_meters | 20220918000715 | | Mohammad | 5K | 20221019003050 | | Mohammad | 10K | 20221120011017 | | Mohammad | half_marathon | 20221221021157 | | Mohammad | full_marathon | 20230122040210 | +-------------+---------------+----------------+ 10 rows in set (0.00 sec)
ستلاحظ أن القيم المُعادة في عمود total_time
تظهر على نحوٍ مطوّل وقد تصعب قراءتها. لذا سنشرح في قسمٍ لاحق ضمن هذا المقال كيفية استخدام دالة CAST
لتنسيق هذه القيم بطريقة تجعلها أوضح وأسهل للقراءة.
بفرض أنّ تركيزنا منصب على أداء العدّائين في السباقات ذات المسافات الأطول، من قبيل سباقات نصف الماراثون والماراثون الكامل، سنستخدم استعلامًا لاسترجاع هذه البيانات على وجه الخصوص. إذ سنطرح زمن الانتهاء end_time
من زمن البدء start_time
مُستخدمين بنية WHERE
للتحديد الدقيق للنتائج، لتشمل فقط السباقات التي تزيد مسافتها في العمود total_miles
عن 12 ميل:
mysql> SELECT runner_name, race_name, end_time - start_time AS half_full_results mysql> FROM race_results mysql> WHERE total_miles > 12;
الخرج +-------------+---------------+-------------------+ | runner_name | race_name | half_full_results | +-------------+---------------+-------------------+ | Ahmad | half_marathon | 20221221013904 | | Ahmad | full_marathon | 20230122032310 | | Mohammad | half_marathon | 20221221021157 | | Mohammad | full_marathon | 20230122040210 | +-------------+---------------+-------------------+ 4 rows in set (0.00 sec)
أجرينا في هذا القسم بعض العمليات الحسابية على التواريخ والأوقات باستخدام تعليمة SELECT
وذلك لأغراض عملية على البيانات النموذجية التجريبية. فيما يلي، ستتدرب على استخدام استعلامات تشمل دوال متنوعة للتواريخ والأوقات.
استخدام دوال التاريخ والوقت وتعابير الفترات الزمنية
هناك العديد من الدوال التي يُمكن استخدامها لإيجاد ومعالجة قيم التواريخ والأوقات في SQL. إذ تُستخدم الدوال SQL على نحوٍ أساسي لمعالجة البيانات أو التعامل معها والتحكم بها، وتختلف الدوال المتوفرة باختلاف تقديم SQL المُستخدم. بيد أنّ معظم تقديمات SQL تتيح استرجاع القيم الحالية للتاريخ والوقت من خلال الاستعلام عن قيم دالتيّ current_date
وcurrent_time
.
على سبيل المثال، لمعرفة تاريخ اليوم، فالصياغة بسيطة وتتألف فقط من تعليمة SELECT
ودالة current_date
كما في المثال التالي:
mysql> SELECT current_date;
الخرج +--------------+ | current_date | +--------------+ | 2022-02-15 | +--------------+ 1 row in set (0.00 sec)
كما يمكننا إيجاد الوقت الحالي باستخدام نفس الصياغة اعتمادًا على الدالة current_time
، على النحو التالي:
mysql> SELECT current_time;
الخرج +--------------+ | current_time | +--------------+ | 17:10:20 | +--------------+ 1 row in set (0.00 sec)
أمّا إذا كنت تفضل الاستعلام عن كل من التاريخ والوقت معًا في خرجٍ واحد، فاستخدم الدالة current_timestamp
:
mysql> SELECT current_timestamp;
الخرج +---------------------+ | current_timestamp | +---------------------+ | 2022-02-15 19:09:58 | +---------------------+ 1 row in set (0.00 sec)
كما يمكن استخدام دوال التاريخ والوقت كتلك المُستخدمة أعلاه ضمن دوال حسابية على نحوٍ مشابه للقسم السابق من مقالنا. فعلى سبيل المثال، بفرض أنّنا نريد معرفة التاريخ قبل 11 يومًا من تاريخ اليوم الحالي، فيمكننا استخدام نفس الصيغة المُستخدمة سابقًا للاستعلام عن قيمة الدالة current_date
مطروحًا منها العدد 11
لإيجاد التاريخ قبل أحد عشر يومًا:
mysql> SELECT current_date - 11;
الخرج +-------------------+ | current_date - 11 | +-------------------+ | 20220206 | +-------------------+ 1 row in set (0.01 sec)
يُشير هذا الخرج لكون التاريخ قبل 11 يومًا من current_date
(وقت كتابة هذا النص) هو 2022-02-06
، أو 6 فبراير 2022. لنحاول الآن تنفيذ نفس العملية مستبدلين الدالة current_date
بالدالة current_time
:
mysql> SELECT current_time - 11;
الخرج +-------------------+ | current_time - 11 | +-------------------+ | 233639 | +-------------------+ 1 row in set (0.00 sec)
يُظهر هذا الخرج أنه عند طرح 11
من قيمة current_time
، يُطرح فعليًا مقدار 11 ثانية. في حين تُفسّر العملية التي نفذناها سابقًا باستخدام الدالة current_date
العدد 11 على أنه أيام وليس ثواني.
هذا التباين في تفسير الأرقام لدى التعامل مع دوال التاريخ والوقت قد يكون مربكًا. فبدلاً من اضطرارك لمعالجة قيم التاريخ والوقت باستخدام الحسابات الرياضية بهذا الشكل، توفّر العديد من أنظمة إدارة قواعد البيانات وضوحًا أكبر من خلال استخدام تعابير الفترات الزمنية INTERVAL
.
تسمح تعابير الفترات الزمنية INTERVAL
بإيجاد ما سيكون عليه التاريخ أو الوقت قبل أو بعد فترة محددة من تعبير تاريخ أو وقت معين. وتأخذ هذه التعابير الصيغة التالية:
INTERVAL `value` `unit`
على سبيل المثال، لإيجاد التاريخ بعد خمسة أيام من الآن، يُمكننا تشغيل الاستعلام التالي:
mysql> SELECT current_date + INTERVAL '5' DAY AS "5_days_from_today";
أوجدنا في هذا المثال قيمة current_date
، ثم أضفنا إليها تعبير الفترة INTERVAL '5' DAY
. ما سيُعيد التاريخ بعد خمسة أيام من الآن:
الخرج +-------------------+ | 5_days_from_today | +-------------------+ | 2022-03-06 | +-------------------+ 1 row in set (0.00 sec)
وهذا أقل غموضًا بكثير من الاستعلام التالي، الذي ينتج عنه خرج مشابه، وحتى إن لم يكن مطابقًا تمامًا:
mysql> SELECT current_date + 5 AS "5_days_from_today";
الخرج +-------------------+ | 5_days_from_today | +-------------------+ | 20220306 | +-------------------+ 1 row in set (0.00 sec)
يُلاحظ أنه يُمكن أيضًا طرح فترات زمنية من التواريخ أو الأوقات لإيجاد قيم قبل التاريخ المحدد:
mysql> SELECT current_date - INTERVAL '7' MONTH AS "7_months_ago";
الخرج +--------------+ | 7_months_ago | +--------------+ | 2021-08-01 | +--------------+ 1 row in set (0.00 sec)
تعتمد الوحدات المتاحة لك لاستخدامها في تعابير INTERVAL
على نظام إدارة قواعد البيانات DBMS الذي اخترته، ولكن تتوفّر في معظم الأنظمة خيارات من قبيل HOUR
وMINUTE
وSECOND
:
mysql> SELECT current_time + INTERVAL '6' HOUR AS "6_hours_from_now", mysql> current_time - INTERVAL '5' MINUTE AS "5_minutes_ago", mysql> current_time + INTERVAL '20' SECOND AS "20_seconds_from_now";
الخرج +------------------+---------------+---------------------+ | 6_hours_from_now | 5_minutes_ago | 20_seconds_from_now | +------------------+---------------+---------------------+ | 07:51:43 | 01:46:43 | 01:52:03.000000 | +------------------+---------------+---------------------+ 1 row in set (0.00 sec)
الآن وبعد أن اطلعت على تعابير الفترات الزمنية وتعرفت على بعض دوال التاريخ والوقت، الفرصة أمامك لتتدرّب مستخدمًا البيانات التجريبية النموذجية التي أدرجتها في الخطوة الأولى.
استخدام الدالة CAST
ودوال التجميع مع التاريخ والوقت
بالعودة إلى المثال الثالث من قسم استخدام العمليات الحسابية مع التاريخ والوقت، حين نفّذنا الاستعلام التالي لطرح زمن الانتهاء end_time
من زمن البدء start_time
لحساب إجمالي الساعات التي أكملها كل عداء لكل سباق. حصلنا على العمود total_time
والذي يتضمّن ناتج طويل جدًا يتبع نمط البيانات TIMESTAMP
المُحدد لهذا العمود من الجدول:
mysql> SELECT runner_name, race_name, end_time - start_time mysql> AS total_time mysql> FROM race_results;
الخرج +-------------+---------------+----------------+ | runner_name | race_name | total_time | +-------------+---------------+----------------+ | Ahmad | 1600_meters | 20220918000630 | | Ahmad | 5K | 20221019002231 | | Ahmad | 10K | 20221120003805 | | Ahmad | half_marathon | 20221221013904 | | Ahmad | full_marathon | 20230122032310 | | Mohammad | 1600_meters | 20220918000715 | | Mohammad | 5K | 20221019003050 | | Mohammad | 10K | 20221120011017 | | Mohammad | half_marathon | 20221221021157 | | Mohammad | full_marathon | 20230122040210 | +-------------+---------------+----------------+ 10 rows in set (0.00 sec)
ونظرًا لأنّنا نُجري عملية على عمودين بأنماط بيانات مختلفة (عمود end_time
يحمل قيم من نمط TIMESTAMP
وعمود start_time
يحمل قيم من نمط TIME
)، فإنّ قاعدة البيانات لا تعرف أي نمط بيانات يجب أن تستخدم لدى طباعة نتيجة العملية. لذا تحوّل كلا القيمتين إلى أعداد صحيحة لتتمكن من تنفيذ العملية، مما ينتج عنه الأرقام الطويلة في عمود total_time
.
وكحل لجعل هذه البيانات أوضح للقراءة والتفسير، يمكنك استخدام دالة CAST
لتحويل هذه القيم الطويلة من الأعداد الصحيحة إلى نمط بيانات TIME
. وللقيام بذلك، ابدأ بالدالة CAST
ثم اتبعها مباشرةً بقوس فتح ثم القيم التي تريد تحويلها ثم الكلمة المفتاحية AS
متبوعة باسم نمط البيانات الذي تريد التحويل إليه.
الاستعلام التالي مطابق للمثال السابق، ولكنه يستخدم دالة CAST
لتحويل عمود total_time
إلى نمط بيانات TIME
:
mysql> SELECT runner_name, race_name, CAST(end_time - start_time AS time) mysql> AS total_time mysql> FROM race_results;
الخرج +-------------+---------------+------------+ | runner_name | race_name | total_time | +-------------+---------------+------------+ | Ahmad | 1600_meters | 00:06:30 | | Ahmad | 5K | 00:22:31 | | Ahmad | 10K | 00:38:05 | | Ahmad | half_marathon | 01:39:04 | | Ahmad | full_marathon | 03:23:10 | | Mohammad | 1600_meters | 00:07:15 | | Mohammad | 5K | 00:30:50 | | Mohammad | 10K | 01:10:17 | | Mohammad | half_marathon | 02:11:57 | | Mohammad | full_marathon | 04:02:10 | +-------------+---------------+------------+ 10 rows in set (0.00 sec)
حوّلت الدالة CAST
قيم البيانات في الخرج أعلاه إلى نمط البيانات TIME
، ما جعلها أسهل للقراءة والفهم.
لنستخدم الآن بعضًا من دوال التجميع مع دالة CAST
بهدف إيجاد أقصر وأطول توقيت وإجمالي الوقت لكل عدّاء. لنستعلم بدايةً عن أصغر (أو أقصر) مدة زمنية مستغرقة باستخدام دالة التجميع MIN
. ومجددًا لا بدّ من استخدام الدالة CAST
هنا لتحويل قيم البيانات من النمط TIMESTAMP
إلى النمط TIME
مما يجعلها أوضح. وتجدر الملاحظة إلى أنّه عند استخدام دالتين كما في هذا المثال، تتطلب العملية استخدام زوجين من الأقواس الهلالية، إذ يجب أن تكون عملية حساب إجمالي الساعات المُتمثلة في طرح زمن البدء من زمن الانتهاء (end_time - start_time
) متداخلةً ضمن إحداها. وأخيرًا، سنضيف بنية GROUP BY
لتنظيم هذه القيم بناءً على عمود runner_name
بحيث يعرض الخرج نتائج سباقات كلا العدّائين:
mysql> SELECT runner_name, MIN(CAST(end_time - start_time AS time)) AS min_time mysql> FROM race_results GROUP BY runner_name;
الخرج +-------------+----------+ | runner_name | min_time | +-------------+----------+ | Ahmad | 00:06:30 | | Mohammad | 00:07:15 | +-------------+----------+ 2 rows in set (0.00 sec)
يُظهر هذا الخرج أقصر زمن لكل عدّاء، في هذه الحالة الحد الأدنى هو ست دقائق وثلاثون ثانية لأحمد، وسبع دقائق وخمس عشرة ثانية لمحمد.
الآن ولإيجاد أطول زمن لكل عدّاء، يمكننا استخدام نفس الصيغة كما في الاستعلام السابق مستبدلين الدالة MIN
بالدالة MAX
:
mysql> SELECT runner_name, MAX(CAST(end_time - start_time AS time)) AS max_time mysql> FROM race_results GROUP BY runner_name;
الخرج +-------------+----------+ | runner_name | max_time | +-------------+----------+ | Ahmad | 03:23:10 | | Mohammad | 04:02:10 | +-------------+----------+ 2 rows in set (0.00 sec)
يُشير هذا الخرج أن أطول زمن جري لأحمد بلغ كإجمالي ثلاث ساعات وثلاث وعشرين دقيقة وعشر ثوانٍ؛ ولمحمد كان أربع ساعات ودقيقتين وعشر ثوانٍ.
أمّا الآن، لنستعلم عن بعض المعلومات العامة (الخلاصة) حول إجمالي الساعات التي قضاها كل عدّاء في الجري. سندمج في هذا الاستعلام دالة التجميع SUM
لإيجاد المجموع الإجمالي للساعات بناءً على الفرق بين end_time
وstart_time
، كما سنستخدم الدالة CAST
لتحويل هذه قيم البيانات هذه إلى نمط البيانات TIME
. كما لم ننسَ تضمين GROUP BY
لتنظيم قيم نتائج كلا العدّاءين:
mysql> SELECT runner_name, SUM(CAST(end_time - start_time AS time)) mysql> AS total_hours FROM race_results GROUP BY runner_name;
الخرج +-------------+-------------+ | runner_name | total_hours | +-------------+-------------+ | Ahmad | 52880 | | Mohammad | 76149 | +-------------+-------------+ 2 rows in set (0.00 sec)
يُبيّن هذا الخرج على نحوٍ مثير للاهتمام كيفية تفسير MySQL للنتائج، والتي في الواقع تحسب الزمن الإجمالي في هيئة أعداد صحيحة. فلو قرأنا هذه النتائج على أنها أزمنة، فإنّ الرقم المُعبّر عن إجمالي زمن أحمد يُفصّل إلى خمس ساعات وثمان وعشرين دقيقة وثمانين ثانية؛ وزمن محمد يُفصّل إلى سبع ساعات وواحد وستين دقيقة وتسع وأربعين ثانية. ومن الواضح أنّ هذا التفصيل للأزمنة لا يبدو منطقيًا وفقًا للقيم الفعلية، مما يشير إلى أنّ MySQL تعاملت مع الأزمنة كأعداد صحيحة. أمّا إذا جربنا الأمر عينه في نظام إدارة قواعد بيانات مختلف، من قبيل PostgreSQL على سبيل المثال، فسيبدو الاستعلام مختلفًا قليلًا:
postgres=# SELECT runner_name, SUM(CAST(end_time - start_time AS time)) postgres=# AS total_hours FROM race_results GROUP BY runner_name;
الخرج runner_name | total_hours -------------+------------- Mohammad | 10:01:44 Ahmad | 06:09:20 (2 rows)
يُفسّر الاستعلام في PostgreSQL القيم كأزمنة في هذه الحالة، وتُحسب على هذا الأساس، إذ يمكن تفصيل نتائج محمد إلى إجمالي عشر ساعات ودقيقة واحدة وأربع وأربعين ثانية؛ وزمن أحمد إلى ست ساعات وتسع دقائق وعشرين ثانية. وما هذا سوى مثال حول كيفية تفسير تنفيذات أنظمة إدارة قواعد البيانات المختلفة للقيم البيانات على نحوٍ مختلف حتى ولو كانت تستخدم نفس الاستعلام ونفس مجموعة البيانات.
الخلاصة
لعلّ فهم كيفية استخدام التاريخ والوقت في SQL مفيد لدى الاستعلام عن نتائج محددة مثل الدقائق أو الثواني أو الساعات أو الأيام أو الأشهر أو السنوات، أو مزيج من كل هذه الوحدات. ناهيك عن وجود العديد من الدوال المتاحة للتواريخ والأوقات والتي تسهّل العثور على قيم معينة، من قبيل التاريخ أو الوقت الحالي. ورغم استخدامنا في هذا المقال لعمليات حسابية بسيطة مثل الجمع والطرح على التواريخ والأوقات في SQL، ولكن يمكنك استخدام قيم التاريخ والوقت مع أي تعبير رياضي.
وللمزيد حول SQL، نشجعك على متابعة سلسلة تعلم SQL في أكاديمية حسوب.
ترجمة -وبتصرف- للمقال How To Work with Dates and Times in SQL لصاحبه Jeanelle Horcasitas.
أفضل التعليقات
لا توجد أية تعليقات بعد
انضم إلى النقاش
يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.