لوحة المتصدرين
المحتوى الأكثر حصولًا على سمعة جيدة
المحتوى الأعلى تقييمًا في 08/15/23 في كل الموقع
-
السلام عليكم، هل يمكنني تعلم دورة علوم الحسوب وتطوير واجهة المستخدم في نفس الوقت مثل يوم لدورة ويوم لدورة الأخرى؟1 نقطة
-
من الصعب تعلم دورتين معاً في نفس الوقت فليس هناك إستفادة من تعلم الدورتين معاً في نفس الوقت الأفضل تعلم دورة علوم الحاسوب أولاً قبل دورة تطوير واجهة المستخدم . وهناك عدة أسباب لذلك: دورة علوم الحاسوب ستعطيك الأساسيات والمفاهيم التقنية التي ستحتاجها في تطوير واجهات المستخدم. ستتعلم في علوم الحاسوب لغات البرمجة الأساسية مثل Javascript أو Python التي غالبًا ما تستخدم في بناء واجهات المستخدم. ستفهم بشكل أفضل كيفية تخزين البيانات واسترجاعها والتعامل مع قواعد البيانات في تعلم المجالات الأخرى. سيساعدك فهم هيكلة ومعالجة البيانات على تصميم واجهة مستخدم أكثر كفاءة وفي الدورات الأخرى. بشكل عام، الخبرة التي ستكتسبها من علوم الحاسوب ستساعدك كثيرًا في إنشاء واجهات مستخدم ذات كفاءة وأداء أفضل.1 نقطة
-
هل في دورة علوم الحاسوب ضمان عمل حر بقيمة دورة من أكادمية حاسوب بعد حصول على الشهادة ؟1 نقطة
-
نعم كل دورة تؤهلك للحصول على فرصة عمل حر ، لكن دورة علوم الحاسوب بعد أن تنهيها سوف تحتاج إلى تطوير مهاراتك والإستمرار في مجال معين ، ويمكن أن تحصل على فرصة عمل حر بعد الإنتهاء من دورة علوم الحاسوب ، لكن فرصتك سوف تكون أكبر عندما تحدد مجالك وتطور نفسك به .1 نقطة
-
لكن قبل التسجيل قرأت أن ضمان عمل في أي دورة أخترتها، بشرط حصول على شهادة ،وبعد الشهادة إذا لم أحصل على وظيفة أسترجع رسوم التي دفعت1 نقطة
-
وعليكم السلام من وجهة نظري أرى أن الموضوع سوف يكون صعب عليك ، لأن محور ومحتوى الدورتين مختلف وسوف تواجه مشكلة في الجمع بين الدورتين ويجب عليك التركيز على دورة واحدة وإنهائها ومن ثم الإنتقال إلى الدورة الثانية وهكذا سوف تسطيع الإستفادة من محتوى الدورة دون التشتت والضياع بين الدورتين ، لكن في حال اخترت أن تقوم بتطبيق الطريقة التي أخبرت بها يجب عليك أن تجهز نفسك لتركيز عالي.1 نقطة
-
تستطيع فعل ما تريد، لكن الصحيح هو دراسة المسار البرمجي بالتدريج، بمعنى دورة علوم الحاسوب مخصصة لمن ليس لديه أي دراية بالبرمجة ويرغب بدراسة الأساسيات والتعرف على عالم البرمجة بمجالاته المختلفة وتعلم أساسيات لغة برمجة أولى مثل جافاسكريبت وبايثون وتنمية مهارة التفكير المنطقي. بعد ذلك تنتقل إلى التخصص في مجال البرمجة الذي تريده، وأنت اخترت مجال الواجهة الأمامية من خلال دورة تطوير واجهات المستخدم.1 نقطة
-
السلام عليكم , قبل شرائي من العرض الخاص بمدة الصيف لقد اخترت دورة علوم الحاسوب ولكن لا ادري ما الدورة الثانية التي سوف اختارها انني حائر بين تطوير المنتجات مع انني لا اعرف ما هي وبين تطوير واجهات المستخدم والتي لا اعتقد انني سوف استفيد منها1 نقطة
-
عايز اعدل الكود دة ليتم عمل عملية حسابية للكمية فى سعرالوجبةو اضافة خانة لتحديد الكمية من الاصناف الاضافية ثم حساب اجمالى تكلفة الوجبة مع الاصناف المضافة <!DOCTYPE html> <html> <head> <style> .card { width: 100%; max-width: 200px; height: auto; border: 1px solid #000; margin: 10px; padding: 10px; background-color: #ffffff; box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2); display: inline-block; transition: transform 0.5s; cursor: pointer; } .card:hover { transform: scale(1.05); } .image { width: 100%; height: auto; background-color: lightyellow; } .name { margin-top: 10px; font-weight: bold; } .quantity-input { margin-top: 10px; } .add-to-cart { margin-top: 10px; background-color: green; color: white; padding: 5px 10px; border: none; cursor: pointer; } .cart { margin-top: 20px; background-color: lightblue; padding: 10px; } .delete-item { color: red; cursor: pointer; } .whatsapp-button { margin-top: 20px; background-color: blue; color: white; padding: 5px 10px; border: none; cursor: pointer; } @media screen and (min-width: 768px) { .card { width: 200px; } } /* تكبير النمط */ .checkbox { transform: scale(1.5); } /* تظليل الشيك بوكس */ .checkbox input[type="checkbox"] { box-shadow: 0 0 5px #888888; } <!-- استخدام الشيك بوكس --> <div class="checkbox"> <input type="checkbox"> </div> </style> </head> <body> <div id="cards-container"> <div class=""> <img src="meal1.jpg" alt="وجبة 1"> <h3></h3> </div> <div class="card"> <img src="https://eldahan.com.eg/wp-content/uploads/2021/03/%D9%88%D8%AC%D8%A8%D8%A9-%D9%85%D9%8A%D9%83%D8%B3-%D8%AC%D8%B1%D8%A8%D9%84-1.png" alt="وجبة ميكس"> <h3>وجبة ميكس</h3> <p1> 120السعر</p1> <h5>ارز-سلطة-طحينة </h5> <p>الكمية: <input type="number" value="1"> </p> <input type="checkbox" id="بطاطس" name="اضافات[]" value="بطاطس,10"> <label for="بطاطس">بطاطس (10 جنية)</label> <br> <input type="checkbox" id="مشروبات" name="اضافات[]" value="مشروبات,(10 جنية)"> <label for="بطاطس">مشروبات (10 جنية)</label> <br> <button class="button" onclick="addToCart(' وجبة ميكس')">إضافة إلى العربة</button> </div> <div class="card"> <img src="https://eldahan.com.eg/wp-content/uploads/2021/03/%D9%88%D8%AC%D8%A8%D8%A9-%D9%81%D8%B1%D8%A7%D8%AE-%D9%85%D8%B9-%D8%B4%D9%8A%D8%B4.png" alt="وجبة 1"> <h3>وجبة 1</h3> <p>الكمية: <input type="number" value="1"> </p> <input type="checkbox" id="بطاطس" name="اضافات[]" value="بطاطس,10"> <label for="بطاطس">ااااااس</label> <br> <input type="checkbox" id="مشروبات" name="اضافات[]" value="مشروبات,20جنية"> <label for="مشروبات">مشروبات</label> <br> <button class="button" onclick="addToCart('وجبة 1')">إضافة إلى العربة</button> </div> <div class="card"> <img src="meal1.jpg" alt="وجبة 1"> <h3>وجبة 1</h3> <p>الكمية: <input type="number" value="1"> </p> <input type="checkbox" id="بطاطس" name="اضافات[]" value="بطاطس,10"> <label for="بطاطس">ااااااس</label> <br> <input type="checkbox" id="مشروبات" name="اضافات[]" value="مشروبات,10"> <label for="مشروبات">مشروبات</label> <br> <button class="button" onclick="addToCart('وجبة 1')">إضافة إلى العربة</button> </div> <div class="cart"> <h2>سلة المشتريات</h2> <div id="cart-items"></div> <button class="button" onclick="sendCartToWhatsApp()">إرسال الطلب عبر الواتساب</button> </div> <script> var cartItems = []; function addToCart(itemName) { var price = parseInt(document.querySelector('p1').innerHTML); var text = document.querySelector('h5').innerText; var quantity = parseInt(document.querySelector('input[type="number"]').value); var extras = []; var extrascheckboxes = document.querySelectorAll('input[name="اضافات[]"]:checked'); var extras = []; var totalPrice = 0; var totalQuantity = 0; extrascheckboxes.forEach(function(checkbox) { extras.push(checkbox.value); totalPrice += parseFloat(checkbox.dataset.price); totalQuantity += parseFloat(checkbox.dataset.quantity); }); console.log('إجمالي السعر:', totalPrice); console.log('إجمالي الكمية:', totalQuantity); console.log('الإضافات:', extras); var item = { name: itemName, text: text, price: price, quantity: quantity, extras: extras }; cartItems.push(item); updateCart(); } function removeFromCart(index) { cartItems.splice(index, 1); updateCart(); } function calculateTotal() { var total = 0; var cards = document.getElementsByClassName("card"); for (var i = 0; i < cards.length; i++) { var quantity = parseInt(cards[i].querySelector("input[type=number]").value); var price = parseFloat(cards[i].querySelector(".price").textContent.replace("سعر الوجبة: ", "")); // تحقق مما إذا كان صنف فرعي محدد واحتسب سعره إذا لزم الأمر total += (price * quantity); } document.getElementById("cart").textContent = "اجمالي السعر: " + total + " ريال"; } var quantityInputs = document.querySelectorAll("input[type=number]"); for (var i = 0; i < quantityInputs.length; i++) { quantityInputs[i].addEventListener("input", calculateTotal); } function updateCart() { var cartItemsHTML = ''; cartItems.forEach(function(item, index) { cartItemsHTML += '<div class="cart-item">' + '<h4>' + item.name + '</h4>' + '<p1>السعر: ' + item.price + '</p1>' + '<h5>المكونات: ' + item.text + '</h5>' + '<p>الكمية: ' + item.quantity + '</p>' + '<p>الإضافات: ' + item.extras.join(', ') + '</p>' + '<button class="button" onclick="removeFromCart(' + index + ')">حذف</button>' + '</div>'; }); document.getElementById('cart-items').innerHTML = cartItemsHTML; } function sendCartToWhatsApp() { var message = 'الطلبات: \n\n'; cartItems.forEach(function(item) { message += 'وجبة: ' + item.name + '\n'; message += 'السعر: ' + item.price + '\n'; message += 'المكونات: ' + item.text + '\n'; message += 'الكمية: ' + item.quantity + '\n'; message += 'الإضافات: ' + item.extras.join(', ') + '\n\n'; }); var phoneNumber = '0123456789'; // رقم الهاتف المحدد // يمكنك تعديل الرسالة ورقم الهاتف حسب الاحتياجات الخاصة بك window.open('https://api.whatsapp.com/send?phone=' + 0201061710999 + '&text=' + encodeURIComponent(message)); } </script> </body> </html>1 نقطة
-
هناك بدائل لخدمة Gravatar التي يمكنك استخدامها لعرض صور المستخدمين بدلاً منها. إليك بعض البدائل المشهورة: Avatar.js: هذه المكتبة توفر واجهة برمجة تطبيقات (API) لإنشاء صور البروفايل الافتراضية على الخادم الخاص بك. يمكنك تخصيص الألوان والأشكال والرموز والنصوص لإنشاء صور فريدة ومميزة للمستخدمين. يمكنك العثور على المزيد من المعلومات والأمثلة على الموقع الرسمي لـ Avatar.js. DiceBear Avatars: هي مكتبة JavaScript توفر مجموعة من الأيقونات العشوائية والمتنوعة للمستخدمين. تتيح لك هذه المكتبة إنشاء صور بروفايل فريدة بناءً على معرّف فريد للمستخدم، مثل اسم المستخدم أو البريد الإلكتروني. يمكنك الاطلاع على موقع DiceBear للحصول على المزيد من التفاصيل والأمثلة. Adorable Avatars: هي خدمة تقدم صورًا بسيطة وجذابة للمستخدمين. تتيح لك هذه الخدمة توليد صور بروفايل باستخدام عناوين البريد الإلكتروني أو أسماء المستخدمين. يمكنك زيارة موقع Adorable Avatars للاطلاع على المزيد من المعلومات واستخدام الخدمة. وفيما يلي مثال بسيط يوضح كيفية استخدام مكتبة DiceBear Avatars في توليد صورة بروفايل عشوائية: const dicebear = require('dicebear'); const options = {}; // يمكنك تخصيص الخيارات حسب احتياجاتك // توليد عنوان الصورة العشوائية باستخدام DiceBear Avatars const avatar = dicebear.default(options).getUrl(); console.log(avatar); // عنوان الصورة المولدة عشوائياً تُستدعى مكتبة DiceBear Avatars وتتم تعريف الخيارات حسب احتياجاتك. ثم يتم استدعاء `getUrl()` للحصول على عنوان الصورة العشوائية. يمكنك استخدام هذا العنوان في تطبيقك لعرض صورة بروفايل فريدة للمستخدم.1 نقطة
-
عليك بتقبل الأمور بواقعية وبدون تصورات غير حقيقية، دورة تطوير واجهات المستخدم هي بوابة الدخول لمجال تطوير الواجهات الأمامية Front-End بالتالي يتم بها شرح الأساسيات من خلال HTML, CSS, JS, jQuery, Bootstrap. لذلك أنت في مرحلة البداية والتي تؤهلك لإنشاء مواقع ثابتة Static وليست ديناميكية، أي مواقع محتواها لا يتغير يبقى كما هو. وستجد مشاريع لذلك على مستقل وخمسات أي على مواقع العمل الحر، لكن في الشركات المشاريع تتطلب الخبرة بإطار أو مكتبة للواجهة الأمامية مثل React أو Angular أو Vue.js. وستجد هنا توضيح لتلك النقطة: ولذلك أنت بحاجة إلى دورة تطوير التطبيقات باستخدام JavaScript ويتم بها شرح React وإطارات جافاسكريبت الأخرى. وإليك وصف وظيفة خاصة بمطور واجهة أمامية Job Requirements: Deep understanding of JavaScript fundamentals and common techniques. Good Understanding in all ES6/ES7 features. Strong experience in React and it's an ecosystem. Strong experience in the next technologies and libraries: Redux and its ecosystem such as redux-Saga, redux-thunk, redux sauce. JSS React-router Building tools and module-bundlers such as Webpack and Babel + ( Gulp or Grunt ) Linting: eslint and it's common libraries HTML5 / CSS3 and styling predecessors such as: SASS and LESS Experience with Github Familiarity with RESTful APIs.1 نقطة
-
صحيح، يجب عليك تسجيل حساب على موقع Gravatar حتى تتمكن من استخدام ميزة رفع صور الرمز الشخصي، وبعد التسجيل، يمكنك تحديد صورة الرمز الشخصي الخاصة بك وإعداد إعداداتها، ثم استخدام عنوان URL الخاص بـ Gravatar الخاص بك في تطبيقاتك. وإليك الخطوات لتسجيل حساب على Gravatar وإعداد صورة الرمز الشخصي: انتقل إلى موقع Gravatar على الويب. انقر فوق الزر "إنشاء حساب". أدخل عنوان بريدك الإلكتروني وكلمة مرورك. انقر فوق الزر "إنشاء حساب". بعد إنشاء حسابك، يمكنك تحديد صورة الرمز الشخصي الخاصة بك عن طريق النقر فوق الزر "تعيين صورة الرمز الشخصي". يمكنك تحميل صورة من جهاز الكمبيوتر الخاص بك أو اختيار صورة من مجموعة Gravatar. بعد تحديد صورة الرمز الشخصي الخاصة بك، يمكنك إعداد إعداداتها عن طريق النقر فوق الزر "إعدادات الرمز الشخصي". يمكنك تحديد حجم الصورة ونوعها وإعدادات الخصوصية. بعد إعداد إعدادات الرمز الشخصي الخاص بك، يمكنك النقر فوق الزر "حفظ". بمجرد إعداد صورة الرمز الشخصي الخاصة بك، تستطيع استخدام عنوان URL الخاص بـ Gravatar في تطبيقاتك. مثلاً استخدام عنوان URL الخاص بـ Gravatar الخاص بك في النموذج التالي: <img src="https://gravatar.com/avatar/[your_email_address]?s=200&r=pg&d=mm" /> وسيعرض ذلك الكود صورة الرمز الشخصي الخاصة بك بحجم 200 بكسل وتنسيق صورة شخصي وخلفية بيضاء.1 نقطة
-
يبدو أنك قمت بتعيين الصورة الافتراضية "mm" في حالة عدم توفر صورة Gravatar للمستخدم. نعم يتطلب استخدام خدمة Gravatar للحصول على صورة المستخدم التسجيل في الموقع باستخدام عنوان البريد الإلكتروني الخاص بك. لاستخدام Gravatar في مشروعك ، يمكنك إعطاء المستخدمين إمكانية تعيين صور شخصية لحساباتهم وتحميلها على موقع Gravatar باستخدام عنوان البريد الإلكتروني الخاص بهم. لحل مشكلتك والحصول على الصورة المصغرة للمستخدم سريعًا بدون تسجيل في Gravatar، يمكنك تجربة استخدام البرنامج التالي: const gravatar = require('gravatar'); const avatar = gravatar.url(email, { s: '200', r: 'pg', d: '404' }); تم استبدال قيمة `d` بـ `'404'` بدلاً من `'mm'`. هذا يعني أنه إذا لم تتوفر صورة Gravatar للمستخدم، سيتم عرض صورة 404 الافتراضية بدلاً من صورة البديلة. بعد تعديل البرنامج، يجب أن تحصل على الصورة المصغرة للمستخدم دون الحاجة إلى تسجيل في Gravatar.1 نقطة
-
يمكنك الوصول لأكاديمية حسوب من خلال العديد من الطرق قم بالبحث في محرك البحث جوجل أوغيره وأكتب موسوعة حسوب وسيظهر لك الموقع يمكنك الوصول إلى الموقع من خلال أكاديمية حسوب عن طريق النزول لأسفل أي صفحة في موقع أكاديمية حسوب وستجد رابط لموسوعة حسوب يمكنك الوصول من خلال هذا الرابط1 نقطة
-
تمام لكن ظهر لى مشكله اخره انه عند وجود نص قبل التاريخ لن يحدده ولذلك اضفت هذا الجزء (\D*?) على السطر الخاص بك هل هذا صحيح وشكرا لك مقدما1 نقطة
-
تدمج العبارة JOIN البيانات من جدولين، وتعيد مجموعة مختلطة من الأعمدة من كلا الجدولين، وذلك حسب نوع الضمّ المُستخدم، ومعاييره (كيفية ربط الصفوف من كلا الجدولين). يمكن ضمّ جدولٍ إلى نفسه، أو بأيّ جدول آخر. وإذا كانت هناك حاجة للوصول إلى معلومات من أكثر من جدولين، فيمكن استخدام الضمّ عدّة مرّات في عبارة FROM. الضمّ الذاتي Self Join يمكن ضمّ جدول إلى نفسه، بحيث تتطابق الصفوف مع بعضها البعض وفق شروط معينة. في مثل هذه الحالة، يجب استخدام الكُنى (aliases) للتمييز بين العناصر المكرّرة من الجدول. في المثال التالي، لكلّ موظّف في جدول الموظّفين Employees، يُعاد سجلّ يحتوي الاسم الأول للموظّف، والاسم الأول لمديره. ولمّا كان المدراء هم أيضًا موظفين، فسنضمّ الجدول إلى نفسه: SELECT e.FName AS "Employee", m.FName AS "Manager" FROM Employees e JOIN Employees m ON e.ManagerId = m.Id سيعيد هذا الاستعلام البيانات التالية: table { width: 100%; } thead { vertical-align: middle; text-align: center; } td, th { border: 1px solid #dddddd; text-align: right; padding: 8px; text-align: inherit; } tr:nth-child(even) { background-color: #dddddd; } Employee Manager John James Michael James Johnathon John شرح الاستعلام يحتوي الجدول الأصلي على هذه السجلات: Id FName LName PhoneNumber ManagerId DepartmentId Salary HireDate 1 James Smith 1234567890 NULL 1 1000 01-01-2002 2 John Johnson 2468101214 1 1 400 23-03-2005 3 Michael Williams 1357911131 1 2 600 12-05-2009 4 Johnathon Smith 1212121212 2 1 500 24-07-2016 الخطوة الأولى في تنفيذ الاستعلام هي إجراء جداء ديكارتي لجميع السجلات في الجداول المستخدمة في عبارة FROM. في حالتنا هذه، استخدمنا جدول الموظفين مرّتين، لذا سيبدو الجدول الوسيط كما يلي (أزلنا الحقول غير المستخدمة في المثال): e.Id e.FName e.ManagerId m.Id m.FName m.ManagerId 1 James NULL 1 James NULL 1 James NULL 2 John 1 1 James NULL 3 Michael 1 1 James NULL 4 Johnathon 2 2 John 1 1 James NULL 2 John 1 2 John 1 2 John 1 3 Michael 1 2 John 1 4 Johnathon 2 3 Michael 1 1 James NULL 3 Michael 1 2 John 1 3 Michael 1 3 Michael 1 3 Michael 1 4 Johnathon 2 4 Johnathon 2 1 James NULL 4 Johnathon 2 2 John 1 4 Johnathon 2 3 Michael 1 4 Johnathon 2 4 Johnathon 2 الخطوة التالية هي ترشيح السجلات، والإبقاء على السجلات التي تفي بشرط الضمّ وحسب، أي سجلات الجدول e التي يساوي الحقل ManagerId خاصتها الحقلَ Id في الجدول m: e.Id e.FName e.ManagerId m.Id m.FName m.ManagerId 2 John 1 1 James NULL 3 Michael 1 1 James NULL 4 Johnathon 2 2 John 1 بعد ذلك، تُقيّم كل التعبيرات المستخدمة في عبارة SELECT لإعادة الجدول التالي: e.FName m.FName John James Michael James Johnathon John أخيرًا، يُستبدل اسما العمودين e.FName و m.FName بكُنيتيهما: Employee Manager John James Michael James Johnathon John الاختلاف بين الضم الداخلي والخارجي هناك عدّة أنواع من الضمّ في SQL، وتختلف تلك الأنواع عن بعضها من حيث ما إذا كانت الصفوف التي (لا) تحقّق الشرط ستُضمّ أم لا. هذه بعض أهمّ أنواع الضمّ: INNER JOIN و LEFT OUTERJOINوRIGHT OUTER JOINوFULL OUTER JOIN(الكلمتان المفتَاحيتانINNERوOUTER` اختياريتان). يوضّح الشكل أدناه الاختلافات بين مختلف أنواع الضمّ: تمثل المنطقة الزرقاء النتائج المُعادة من عملية الضمّ، فيما تمثّل المنطقة البيضاء النتائج التي لن تعيدها عملية الضمّ. وهذه صورة لتمثيل الضمّ المتقاطع (Join SQL) مصدر الصورة على سبيل المثال، إليك الجدولين التاليين: A B - - 1 3 2 4 3 5 4 6 لاحظ أنّ القيمتين (1،2) حصريتان للجدول A، أمّا القيمتان (3،4) فمُشتركتان، و القيمتان (5،6) حصريتان لـ B. الضمّ الداخلي يعيد الضم الداخلي تقاطع الجدولين، أي الصفوف المشترك بينهما: select * from a INNER JOIN b on a.a = b.b; select a.*,b.* from a,b where a.a = b.b; a | b --+-- 3 | 3 4 | 4 الضم الخارجي اليساري Left outer join يعيد الضم الخارجي اليساري جميع صفوف A، بالإضافة إلى الصفوف المشتركة مع B: select * from a LEFT OUTER JOIN b on a.a = b.b; a | b --+----- 1 | null 2 | null 3 | 3 4 | 4 الضم الخارجي اليميني Right outer join وبالمثل، يعيد الضمّ الخارجي اليميني كل صفوف B، بالإضافة إلى الصفوف المشتركة في A: select * from a RIGHT OUTER JOIN b on a.a = b.b; a | b -----+---- 3 | 3 4 | 4 null | 5 null | 6 الضمّ الخارجي التام Full outer join يعيد الضمّ الخارجي التام اتحاد A و B، أي جميع الصفوف الموجودة في A وجميع الصفوف الموجودة في B. إذا كانت هناك بيانات في A بدون بيانات مقابلة في B، فسيكون الجزء الخاص بـ B معدوما (null). والعكس صحيح. select * from a FULL OUTER JOIN b on a.a = b.b; a | b -----+----- 1 | null 2 | null 3 | 3 4 | 4 null | 6 null | 5 اصطلاحات الضمّ JOIN Terminology لنفترض أنّ لدينا جدولين A و B، وأنّ بعض صفوفِهما متطابقة (وفق شرط JOIN): هناك عدّة أنواع مختلفة من الضمّ يمكن استخدامها لأجل تضمين أو استبعاد الصفوف التي (لا) تحقق شرط الضمّ في كلا الجانبين. تستخدم الأمثلة أدناه البيانات التالية: CREATE TABLE A ( X varchar(255) PRIMARY KEY ); CREATE TABLE B ( Y varchar(255) PRIMARY KEY ); INSERT INTO A VALUES ('Amy'), ('John'), ('Lisa'), ('Marco'), ('Phil'); INSERT INTO B VALUES ('Lisa'), ('Marco'), ('Phil'), ('Tim'), ('Vincent'); الضمّ الداخلي Inner Join يجمع الضمّ الداخلي بين الصفوف اليسرى واليمنى المتطابقة. SELECT * FROM A JOIN B ON X = Y; X Y ------ ----- Lisa Lisa Marco Marco Phil Phil الضم الخارجي اليساري Left outer join يُسمّى اختصارًا الضمّ اليساري. ويجمع بين الصفوف اليسرى واليمنى التي تحقّق الشرط، مع تضمين الصفوف اليسرى التي لا تحقّق الشرط. SELECT * FROM A LEFT JOIN B ON X = Y; X Y ----- ----- Amy NULL John NULL Lisa Lisa Marco Marco Phil Phil الضم الخارجي اليميني Right outer join يُسمّى اختصارًا الضمّ الأيمن. ويجمع بين الصفوف اليسرى واليمنى التي تحقّق الشرط، مع تضمين الصفوف اليمنى التي لا تحقّق الشرط. SELECT * FROM A RIGHT JOIN B ON X = Y; X Y ----- ------- Lisa Lisa Marco Marco Phil Phil NULL Tim NULL Vincent الضمّ الخارجي التام Full outer join يُسمّى اختصارًا الضمّ التام. وهو اتحاد لعمليتي الضم اليساري واليميني. SELECT * FROM A FULL JOIN B ON X = Y; X Y ----- ------- Amy NULL John NULL Lisa Lisa Marco Marco Phil Phil NULL Tim NULL Vincent الضمّ شبه اليساري يضمّ هذا النوع الصفوفَ اليُسرى التي تتطابق مع الصفوف اليمنى. SELECT * FROM A WHERE X IN (SELECT Y FROM B); X ----- Lisa Marco Phil الضمّ شبه اليميني Right Semi Join يضمّ هذا النوع الصفوف اليمنى التي تطابق الصفوف اليسرى. SELECT * FROM B WHERE Y IN (SELECT X FROM A); Y ----- Lisa Marco Phil لا توجد صياغة للعبارة IN مُخصّصة للضمّ شبه اليساري أو شبه اليميني - كلّ ما عليك فعله هو تبديل مواضع الجدول في SQL. الضمّ شبه اليساري المعكوس Left Anti Semi Join يُضمِّن هذا النوع الصفوفَ اليُسرى التي لا تتطابق مع الصفوف اليمنى. SELECT * FROM A WHERE X NOT IN (SELECT Y FROM B); X ---- Amy John تنبيه: استخدام NOT IN في الأعمدة التي تقبل القيم المعدومة NULL قد يسبّب بعض المشاكل (المزيد من التفاصيل هنا). الضمّ شبه اليميني المعكوس Right Anti Semi Join يُضمِّن هذا النوع الصفوف اليمنى التي لا تطابق الصفوف اليسرى. SELECT * FROM B WHERE Y NOT IN (SELECT X FROM A); Y ------- Tim Vincent لا توجد صياغة للعبارة IN مخصّصة للضمّ شبه اليساري أو شبه اليميني المعكوس - كلّ ما عليك فعله هو تبديل مواضع الجدول في SQL. الضم المتقاطع Cross Join يُجري هذا النوع من الضمّ جداءً ديكارتيًا (Cartesian product) بين الصوف اليسرى والصفوف اليمنى. SELECT * FROM A CROSS JOIN B; X Y ----- ------- Amy Lisa John Lisa Lisa Lisa Marco Lisa Phil Lisa Amy Marco John Marco Lisa Marco Marco Marco Phil Marco Amy Phil John Phil Lisa Phil Marco Phil Phil Phil Amy Tim John Tim Lisa Tim Marco Tim Phil Tim Amy Vincent John Vincent Lisa Vincent Marco Vincent Phil Vincent يكافئ الضمّ المتقاطع ضمًّا داخليًا ذا شرط يتحقّق دائمًا، لذا سيعيد الاستعلام التالي النتيجة نفسها: SELECT * FROM A JOIN B ON 1 = 1; الضمّ الذاتي Self-Join يشير هذا النوع من الضم إلى ضمّ الجدول إلى نفسه. يمكن أن تكون عملية الضمّ الذاتي من أيّ نوع من أنواع الضمّ التي ناقشناها أعلاه. على سبيل المثال، هذا ضمّ ذاتي داخلي ( inner self-join): SELECT * FROM A A1 JOIN A A2 ON LEN(A1.X) < LEN(A2.X); X X ---- ----- Amy John Amy Lisa Amy Marco John Marco Lisa Marco Phil Marco Amy Phil الضمّ الخارجي اليساري Left Outer Join يضمن الضمّ الخارجي اليساري (المعروف أيضًا باسم الضمّ اليساري أو الضمّ الخارجي) تمثيل جميع صفوف الجدول الأيسر؛ وفي حال عدم وجود صفّ مطابق في الجدول الأيمن، فسيُعطى الحقل المقابل القيمةَ NULL. سيختار المثال التالي جميع الأقسام (departments) والأسماء الأولى للموظّفين الذين يعملون في تلك الأقسام. وستُعاد الأقسام التي لا تحتوي على أيّ موظفين، مع إعطاء اسم الموظف المقابل لها القيمة NULL: SELECT Departments.Name, Employees.FName FROM Departments LEFT OUTER JOIN Employees ON Departments.Id = Employees.DepartmentId سنحصل على الخرج التالي: Departments.Name Employees.FName HR James HR John HR Johnathon Sales Michael Tech NULL شرح الاستعلام يوجد جدولان في عبارة FROM، وهما: Id FName LName PhoneNumber ManagerId DepartmentId Salary HireDate 1 James Smith 1234567890 NULL 1 1000 01-01-2002 2 John Johnson 2468101214 1 1 400 23-03-2005 3 Michael Williams 1357911131 1 2 600 12-05-2009 4 Johnathon Smith 1212121212 2 1 500 24-07-2016 وهذا هو الجدول الثاني: Id Name 1 HR 2 Sales 3 Tech في المرحلة الأولى، يُنشأ جداء ديكارتي للجدولين، وينتج عنه جدول وسيط. يُغلَّظُ خطّ السجلات التي تفي بشرط الضمّ (والذي هو في هذه الحالة: Departments.Id = Employees.DepartmentId)؛ وتُمرَّر إلى المرحلة التالية من الاستعلام. لمّا كان هذا الضّمّ ضمًّا خارجيًا يساريًا (LEFT OUTER JOIN)، فستُعاد جميع السجلّات الموجودة في الجانب الأيسر من الضمّ (أي الأقسام Departments)، في حين تُعطى السجلات الموجودة على الجانب الأيمن القيمة المعدومة (NULL) في حال لم تُطابق شرط الضمّ. Id Name Id FName LName PhoneNumber ManagerId DepartmentId Salary HireDate 1 HR 1 James Smitd 1234567890 NULL 1 1000 01-01-2002 1 HR 2 John Johnson 2468101214 1 1 400 23-03-2005 1 HR 3 Michael Williams 1357911131 1 2 600 12-05-2009 1 HR 4 Johnatdon Smitd 1212121212 2 1 500 24-07-2016 2 Sales 1 James Smith 1234567890 NULL 1 1000 01-01-2002 2 Sales 2 John Johnson 2468101214 1 1 400 23-03-2005 2 Sales 3 Michael Williams 1357911131 1 2 600 12-05-2009 2 Sales 4 Johnathon Smith 1212121212 2 1 500 24-07-2016 3 Tech 1 James Smith 1234567890 NULL 1 1000 01-01-2002 3 Tech 2 John Johnson 2468101214 1 1 400 23-03-2005 3 Tech 3 Michael Williams 1357911131 1 2 600 12-05-2009 3 Tech 4 Johnathon Smith 1212121212 2 1 500 24-07-2016 بعد ذلك، تُقيّم كل التعبيرات المستخدَمة في عبارة SELECT لإعادة الجدول التالي: Departments.Name Employees.FName HR James HR John Sales Richard Tech NULL الضمّ الضمني Implicit Join يمكن أيضًا إجراء عملية الضمّ على عدّة جداول، حيث توضع في عبارة from مفصولة بالفاصلة ,، مع تحديد العلاقة بينها في العبارة where. تسمى هذه التقنية "الضمّ الضمني" - Implicit Join - (لأنها لا تحتوي فعليًا العبارةَ join). تدعم جميع أنظمة معالجة قواعد البيانات (RDBMSs) هذه التقنية، ولكن ينصح بتجنّب استخدامها للأسباب التالية: قد تتداخل صياغة الضمّ الضمني مع صياغة الضمّ المتقاطع (cross join)، وهو ما قد يؤدي إلى إعادة نتائج غير صحيحة، خاصةً إذا كان الاستعلام يحتوي الكثير من عمليات الضمّ. إذا كنت تنوي استخدام الضم المتقاطع، فلن يكون ذلك واضحًا من الصياغة (اكتب CROSS JOIN بدلاً من ذلك)، ومن المحتمل أن يعدّلها شخص ما أثناء صيانة الشيفرة دون أن ينتبه. سيختار المثال التالي أسماء الموظفين الأولى وكذلك أسماء الأقسام التي يعملون فيها: SELECT e.FName, d.Name FROM Employee e, Departments d WHERE e.DeptartmentId = d.Id سنحصل على الخرج التالي: e.FName d.Name James HR John HR Richard Sales الضم المتقاطع CROSS JOIN يُجري الضمّ المتقاطع جداءً ديكارتيًا (Cartesian product) على جدولين (الجداء الديكارتي هو عملية تُجمِّع كلّ صفّ من الجدول الأول مع كل صفّ من الجدول الثاني). على سبيل المثال، إذا كان كلّ من الجدولين TABLEA و TABLEB يحتويان 20 صفًا، فستتألّف النتيجة المُعادة من 20*20 = 400 صفًّا. إليك المثال التالي: SELECT d.Name, e.FName FROM Departments d CROSS JOIN Employees e; سنحصل على الخرج التالي: d.Name e.FName HR James HR John HR Michael HR Johnathon Sales James Sales John Sales Michael Sales Johnathon Tech James Tech John Tech Michael Tech Johnathon يوصى بكتابة CROSS JOIN بشكل صريح إن أردت إجراء ضمّ ديكارتي دفعًا للُّبس. التطبيق المتقاطع و الضم الحرفي CROSS APPLY & LATERAL JOIN هناك نوع خاص من الضمّ يُسمّى الضمّ الحرفي LATERAL JOIN (أضيف حديثًا إلى الإصدار 9.3 وما بعده من PostgreSQL)، والذي يُعرف أيضًا باسم التطبيق المتقاطع CROSS APPLY أو التطبيق الخارجي OUTER APPLY في كلّ من SQL Server و Oracle. الفكرة الأساسية التي ينبني عليها هذا النوع من الضمّ هي أنه سيتم تطبيق دالة (أو استعلام فرعي مضمّن - inline subquery) على كل الصفوف المضمومة. يتيح هذا التحكم في عملية الضمّ، مثلًا يمكنك الاكتفاء بضمّ أوّل مُدخل يحقّق شرط الضمّ (matching entry) في الجدول الآخر. يكمن الاختلاف بين الضمّ العادي والضمّ الحرفي في حقيقة أنّه يمكنك استخدام عمود سبق أن ضممته في الاستعلام الفرعي (subquery) الذي طبّقته تقاطعيًا (CROSS APPLY). هذه صياغة الضم الحرفي. PostgreSQL 9.3 والإصدارات الأحدث: left | right | inner JOIN LATERAL SQL Server CROSS | OUTER APPLY INNER JOIN LATERAL و CROSS APPLY متكافئتان، وكذلك LEFT JOIN LATERAL و OUTER APPLY إليك المثال التالي (الإصدار 9.3 وما بعده من PostgreSQL): SELECT * FROM T_Contacts --LEFT JOIN T_MAP_Contacts_Ref_OrganisationalUnit ON MAP_CTCOU_CT_UID = T_Contacts.CT_UID AND MAP_CTCOU_SoftDeleteStatus = 1 --WHERE T_MAP_Contacts_Ref_OrganisationalUnit.MAP_CTCOU_UID IS NULL -- 989 LEFT JOIN LATERAL ( SELECT --MAP_CTCOU_UID MAP_CTCOU_CT_UID ,MAP_CTCOU_COU_UID ,MAP_CTCOU_DateFrom ,MAP_CTCOU_DateTo FROM T_MAP_Contacts_Ref_OrganisationalUnit WHERE MAP_CTCOU_SoftDeleteStatus = 1 AND MAP_CTCOU_CT_UID = T_Contacts.CT_UID /* AND ( (__in_DateFrom <= T_MAP_Contacts_Ref_OrganisationalUnit.MAP_KTKOE_DateTo) AND (__in_DateTo >= T_MAP_Contacts_Ref_OrganisationalUnit.MAP_KTKOE_DateFrom) ) */ ORDER BY MAP_CTCOU_DateFrom LIMIT 1 ) AS FirstOE وهذا مثال يخصّ SQL-Server: SELECT * FROM T_Contacts --LEFT JOIN T_MAP_Contacts_Ref_OrganisationalUnit ON MAP_CTCOU_CT_UID = T_Contacts.CT_UID AND MAP_CTCOU_SoftDeleteStatus = 1 --WHERE T_MAP_Contacts_Ref_OrganisationalUnit.MAP_CTCOU_UID IS NULL -- 989 -- CROSS APPLY -- = INNER JOIN OUTER APPLY -- = LEFT JOIN ( SELECT TOP 1 --MAP_CTCOU_UID MAP_CTCOU_CT_UID ,MAP_CTCOU_COU_UID ,MAP_CTCOU_DateFrom ,MAP_CTCOU_DateTo FROM T_MAP_Contacts_Ref_OrganisationalUnit WHERE MAP_CTCOU_SoftDeleteStatus = 1 AND MAP_CTCOU_CT_UID = T_Contacts.CT_UID /* AND ( (@in_DateFrom <= T_MAP_Contacts_Ref_OrganisationalUnit.MAP_KTKOE_DateTo) AND (@in_DateTo >= T_MAP_Contacts_Ref_OrganisationalUnit.MAP_KTKOE_DateFrom) ) */ ORDER BY MAP_CTCOU_DateFrom ) AS FirstOE الضم التام FULL JOIN هناك نوع آخر من الضمّ أقل شهرة من غيره، وهو الضمّ التام FULL JOIN (ملاحظة: لا تدعم MySQL الضمّ التام) يعيد الضمّ التام الخارجي FULL OUTER JOIN جميع صفوف الجدول الأيسر، وكذلك جميع صفوف الجدول الأيمن. ستُدرج صفوف الجدول الأيسر التي ليس لها مُطابِقَات مقابلة في الجدول الأيمن، وكذلك في الحالة المعكوسة. إليك المثال التالي: SELECT * FROM Table1 FULL JOIN Table2 ON 1 = 2 وهذا مثال آخر: SELECT COALESCE(T_Budget.Year, tYear.Year) AS RPT_BudgetInYear ,COALESCE(T_Budget.Value, 0.0) AS RPT_Value FROM T_Budget FULL JOIN tfu_RPT_All_CreateYearInterval(@budget_year_from, @budget_year_to) AS tYear ON tYear.Year = T_Budget.Year إن كنت تستخدم عمليات الحذف اللينة soft-deletes (والتي لا تحذف البيانات بشكل نهائي)، فسيتعيّن عليك التحقق من حالة الحذف الليّن مرة أخرى في عبارة WHERE (لأنّ سلوك الضمّ التام - FULL JOIN - يتصرف بشكل يشبه الاتحاد UNION)؛ عند إجراء الضمّ التام، سيتعيّن عليك عادةً السماح بـاستخدام القيمة المعدومة NULL في عبارة WHERE؛ وفي حال نسيت ذلك، فسيتصرّف الضمّ كما لو كان ضمًّا داخليًا (INNER join)، وهو ما لا تريده عند إجراء الضمّ التام. إليك المثال التالي: SELECT T_AccountPlan.AP_UID ,T_AccountPlan.AP_Code ,T_AccountPlan.AP_Lang_EN ,T_BudgetPositions.BUP_Budget ,T_BudgetPositions.BUP_UID ,T_BudgetPositions.BUP_Jahr FROM T_BudgetPositions FULL JOIN T_AccountPlan ON T_AccountPlan.AP_UID = T_BudgetPositions.BUP_AP_UID AND T_AccountPlan.AP_SoftDeleteStatus = 1 WHERE (1=1) AND (T_BudgetPositions.BUP_SoftDeleteStatus = 1 OR T_BudgetPositions.BUP_SoftDeleteStatus IS NULL) AND (T_AccountPlan.AP_SoftDeleteStatus = 1 OR T_AccountPlan.AP_SoftDeleteStatus IS NULL) الضم العودي Recursive JOIN يُستخدم الضمّ العودي عادة للحصول على بيانات من نوع أب-ابن (parent-child data). في SQL، تُقدّم عمليات الضمّ العودية باستخدام تعبيرات الجدول العادية كما يوضّح المثال التالي: WITH RECURSIVE MyDescendants AS ( SELECT Name FROM People WHERE Name = 'John Doe' UNION ALL SELECT People.Name FROM People JOIN MyDescendants ON People.Name = MyDescendants.Parent ) SELECT * FROM MyDescendants; الضم الداخلي الصريح يستعلم الضمّ الأولي - basic join (يُسمّى أيضًا الضمّ الداخلي - inner join) عن البيانات من جدولين، حيث تُحدَّد العلاقة بينهما في عبارة join. يستعلم المثال التالي عن أسماء الموظفين (FName) من جدول الموظفين Employees، وأسماء الأقسام التي يعملون فيها (Name) من جدول الأقسام Departments: SELECT Employees.FName, Departments.Name FROM Employees JOIN Departments ON Employees.DepartmentId = Departments.Id سنحصل على الخرج التالي: Employees.FName Departments.Name James HR John HR Richard Sales الضم في استعلام فرعي Joining on a Subquery غالبًا ما يُستخدم الضمّ في الاستعلامات الفرعية (subquery) للحصول على بيانات مُجمّعة (aggregate data) من جدول يحتوي التفاصيل (الجدول الإبن) وعرضها جنبًا إلى جنب مع السجلات من الجدول الأصلي (الجدول الأب). على سبيل المثال، قد ترغب في الحصول على عدد السجلات الفرعية (child records)، أو متوسط قيم عمود معيّن في السجلات الفرعية، أو الصف ذو القيمة الأكبر أو الأصغر. يستخدم هذا المثال الكُنى (لتسهيل قراءة الاستعلامات التي تشمل عدّة جداول)، يعطي المثال فكرة عامّة عن كيفية صياغة عمليات ضمّ الاستعلامات الفرعية. إذ يعيد جميع صفوف الجدول الأصلي "Purchase Orders"، مع إعادة الصف الأول وحسب لكل سجلّ أصلي (parent record) من الجدول الفرعي PurchaseOrderLineItems. SELECT po.Id, po.PODate, po.VendorName, po.Status, item.ItemNo, item.Description, item.Cost, item.Price FROM PurchaseOrders po LEFT JOIN ( SELECT l.PurchaseOrderId, l.ItemNo, l.Description, l.Cost, l.Price, Min(l.id) as Id FROM PurchaseOrderLineItems l GROUP BY l.PurchaseOrderId, l.ItemNo, l.Description, l.Cost, l.Price ) AS item ON item.PurchaseOrderId = po.Id ترجمة -وبتصرّف- للفصل Chapter 18: JOIN من الكتاب SQL Notes for Professionals اقرأ أيضًا: المقال التالي: تحديث الجداول في SQL المقال السابق: البحث والتنقيب والترشيح في SQL النسخة العربية الكاملة لكتاب ملاحظات للعاملين بلغة SQL 1.0.01 نقطة