# ডেটার সাথে কাজ: রিলেশনাল ডাটাবেস |![ স্কেচনোট [(@sketchthedocs)](https://sketchthedocs.dev) দ্বারা ](../../sketchnotes/05-RelationalData.png)| |:---:| | ডেটার সাথে কাজ: রিলেশনাল ডাটাবেস - _স্কেচনোট [@nitya](https://twitter.com/nitya) দ্বারা_ | সম্ভাবনা আছে আপনি অতীতে তথ্য সংরক্ষণের জন্য একটি স্প্রেডশীট ব্যবহার করেছেন। আপনার কাছে সারি এবং কলামের একটি সেট ছিল, যেখানে সারিগুলো তথ্য (অথবা ডেটা) ধারণ করত, এবং কলামগুলো তথ্য বর্ণনা করত (কখনও কখনও মেটাডেটা বলা হয়)। একটি রিলেশনাল ডাটাবেস এই মূল নীতির উপর নির্মিত, টেবিলের কলাম এবং সারি নিয়ে, যা আপনাকে একাধিক টেবিল জুড়ে তথ্য ছড়িয়ে রাখতে দেয়। এটি আপনাকে আরও জটিল ডেটার সাথে কাজ করতে, পুনরাবৃত্তি এড়াতে এবং ডেটা অনুসন্ধানের পদ্ধতিতে নমনীয়তা প্রদান করে। চলুন রিলেশনাল ডাটাবেসের ধারণাগুলো অন্বেষণ করি। ## [পূর্ব-লেকচার কুইজ](https://ff-quizzes.netlify.app/en/ds/quiz/8) ## সবকিছু শুরু হয় টেবিল থেকে একটি রিলেশনাল ডাটাবেসের মূল হলো টেবিল। স্প্রেডশীটের মতো, একটি টেবিল হলো কলাম এবং সারির সমষ্টি। সারিতে থাকে ডেটা বা তথ্য যা আমরা কাজ করতে চাই, যেমন একটি শহরের নাম বা বৃষ্টিপাতের পরিমাণ। কলামগুলো সেই ডেটা বর্ণনা করে যা তারা সংরক্ষণ করে। চলুন আমাদের অনুসন্ধান শুরু করি একটি টেবিল তৈরি করে শহরগুলোর তথ্য সংরক্ষণের জন্য। আমরা তাদের নাম এবং দেশ দিয়ে শুরু করতে পারি। আপনি এটি একটি টেবিলে নিম্নরূপ সংরক্ষণ করতে পারেন: | শহর | দেশ | | -------- | ------------- | | টোকিও | জাপান | | আটলান্টা | যুক্তরাষ্ট্র | | অকল্যান্ড | নিউজিল্যান্ড | দ্রষ্টব্য করুন কলামের নাম **শহর**, **দেশ** এবং **জনসংখ্যা** ডেটা সংরক্ষণের বর্ণনা দেয়, এবং প্রতিটি সারিতে একটি শহরের তথ্য থাকে। ## একক টেবিল পদ্ধতির সীমাবদ্ধতা সম্ভাবনা আছে, উপরের টেবিলটি আপনার কাছে পরিচিত মনে হচ্ছে। চলুন আমাদের ডাটাবেসে কিছু অতিরিক্ত ডেটা যোগ করি - বার্ষিক বৃষ্টিপাত (মিলিমিটারে)। আমরা ২০১৮, ২০১৯ এবং ২০২০ সালের উপর ফোকাস করব। যদি আমরা টোকিওর জন্য এটি যোগ করি, তাহলে এটি এরকম দেখাতে পারে: | শহর | দেশ | বছর | পরিমাণ | | ----- | ------- | ---- | ------ | | টোকিও | জাপান | ২০২০ | ১৬৯০ | | টোকিও | জাপান | ২০১৯ | ১৮৭৪ | | টোকিও | জাপান | ২০১৮ | ১৪৪৫ | আপনি আমাদের টেবিল সম্পর্কে কী লক্ষ্য করেন? আপনি লক্ষ্য করতে পারেন আমরা শহরের নাম এবং দেশ বারবার পুনরাবৃত্তি করছি। এটি অনেক স্টোরেজ নেবে এবং একাধিক কপি থাকা প্রায়ই অপ্রয়োজনীয়। শেষ পর্যন্ত, টোকিওর একটি মাত্র নাম আছে যা আমাদের আগ্রহের। ঠিক আছে, চলুন অন্য কিছু চেষ্টা করি। প্রতিটি বছরের জন্য নতুন কলাম যোগ করি: | শহর | দেশ | ২০১৮ | ২০১৯ | ২০২০ | | -------- | ------------- | ---- | ---- | ---- | | টোকিও | জাপান | ১৪৪৫ | ১৮৭৪ | ১৬৯০ | | আটলান্টা | যুক্তরাষ্ট্র | ১৭৭৯ | ১১১১ | ১৬৮৩ | | অকল্যান্ড | নিউজিল্যান্ড | ১৩৮৬ | ৯৪২ | ১১৭৬ | যদিও এটি সারির পুনরাবৃত্তি এড়ায়, এটি কয়েকটি অন্য চ্যালেঞ্জ যোগ করে। আমাদের প্রতিবার নতুন বছর আসলে টেবিলের কাঠামো পরিবর্তন করতে হবে। এছাড়াও, ডেটা বাড়ার সাথে সাথে বছরগুলো কলাম হিসেবে থাকা মানগুলি পুনরুদ্ধার এবং গণনা করা কঠিন করে তুলবে। এই কারণেই আমাদের একাধিক টেবিল এবং সম্পর্কের প্রয়োজন। ডেটা ভেঙে রাখার মাধ্যমে আমরা পুনরাবৃত্তি এড়াতে পারি এবং ডেটার সাথে কাজ করার পদ্ধতিতে আরও নমনীয়তা পেতে পারি। ## সম্পর্কের ধারণা চলুন আমাদের ডেটায় ফিরে যাই এবং নির্ধারণ করি কীভাবে আমরা বিষয়গুলো ভাগ করব। আমরা জানি আমরা শহরের নাম এবং দেশ সংরক্ষণ করতে চাই, তাই এটি সম্ভবত একটি টেবিলে সবচেয়ে ভাল কাজ করবে। | শহর | দেশ | | -------- | ------------- | | টোকিও | জাপান | | আটলান্টা | যুক্তরাষ্ট্র | | অকল্যান্ড | নিউজিল্যান্ড | কিন্তু পরবর্তী টেবিল তৈরি করার আগে, আমাদের প্রতিটি শহরকে কীভাবে রেফারেন্স করব তা নির্ধারণ করতে হবে। আমাদের একটি ধরনের শনাক্তকারী, আইডি বা (প্রযুক্তিগত ডাটাবেস শব্দে) একটি প্রাথমিক কী প্রয়োজন। প্রাথমিক কী হলো একটি মান যা একটি টেবিলের একটি নির্দিষ্ট সারি শনাক্ত করতে ব্যবহৃত হয়। যদিও এটি নিজেই একটি মানের উপর ভিত্তি করে হতে পারে (উদাহরণস্বরূপ শহরের নাম ব্যবহার করা যেতে পারে), এটি প্রায়শই একটি সংখ্যা বা অন্য কোনো শনাক্তকারী হওয়া উচিত। আমরা চাই না আইডি কখনো পরিবর্তিত হোক কারণ এটি সম্পর্ক ভেঙে দেবে। বেশিরভাগ ক্ষেত্রে আপনি দেখতে পাবেন প্রাথমিক কী বা আইডি একটি স্বয়ংক্রিয়ভাবে তৈরি হওয়া সংখ্যা। > ✅ প্রাথমিক কী প্রায়শই PK হিসেবে সংক্ষিপ্ত করা হয় ### cities | city_id | শহর | দেশ | | ------- | -------- | ------------- | | ১ | টোকিও | জাপান | | ২ | আটলান্টা | যুক্তরাষ্ট্র | | ৩ | অকল্যান্ড | নিউজিল্যান্ড | > ✅ আপনি লক্ষ্য করবেন আমরা এই পাঠে "id" এবং "primary key" শব্দগুলো বিনিময়যোগ্যভাবে ব্যবহার করছি। এখানে ধারণাগুলো DataFrames-এ প্রযোজ্য, যা আপনি পরে অন্বেষণ করবেন। DataFrames "primary key" শব্দটি ব্যবহার করে না, তবে আপনি দেখতে পাবেন তারা অনেকটাই একইভাবে আচরণ করে। আমাদের cities টেবিল তৈরি হয়ে গেলে, চলুন বৃষ্টিপাত সংরক্ষণ করি। শহরের সম্পূর্ণ তথ্য পুনরাবৃত্তি করার পরিবর্তে, আমরা আইডি ব্যবহার করতে পারি। আমাদের নিশ্চিত করতে হবে নতুন তৈরি টেবিলেও একটি *id* কলাম আছে, কারণ সব টেবিলে একটি id বা প্রাথমিক কী থাকা উচিত। ### rainfall | rainfall_id | city_id | বছর | পরিমাণ | | ----------- | ------- | ---- | ------ | | ১ | ১ | ২০১৮ | ১৪৪৫ | | ২ | ১ | ২০১৯ | ১৮৭৪ | | ৩ | ১ | ২০২০ | ১৬৯০ | | ৪ | ২ | ২০১৮ | ১৭৭৯ | | ৫ | ২ | ২০১৯ | ১১১১ | | ৬ | ২ | ২০২০ | ১৬৮৩ | | ৭ | ৩ | ২০১৮ | ১৩৮৬ | | ৮ | ৩ | ২০১৯ | ৯৪২ | | ৯ | ৩ | ২০২০ | ১১৭৬ | নতুন তৈরি **rainfall** টেবিলের ভিতরে **city_id** কলামটি লক্ষ্য করুন। এই কলামটি এমন মান ধারণ করে যা **cities** টেবিলের আইডিগুলোর রেফারেন্স। প্রযুক্তিগত রিলেশনাল ডেটা শব্দে, এটিকে **foreign key** বলা হয়; এটি অন্য একটি টেবিলের প্রাথমিক কী। আপনি এটিকে একটি রেফারেন্স বা পয়েন্টার হিসেবে ভাবতে পারেন। **city_id** ১ টোকিওকে রেফারেন্স করে। > [!NOTE] > Foreign key প্রায়শই FK হিসেবে সংক্ষিপ্ত করা হয় ## ডেটা পুনরুদ্ধার আমাদের ডেটা দুইটি টেবিলে বিভক্ত হওয়ায়, আপনি হয়তো ভাবছেন কীভাবে আমরা এটি পুনরুদ্ধার করব। যদি আমরা MySQL, SQL Server বা Oracle এর মতো একটি রিলেশনাল ডাটাবেস ব্যবহার করি, তাহলে আমরা Structured Query Language বা SQL নামক একটি ভাষা ব্যবহার করতে পারি। SQL (কখনও কখনও "সিকুয়েল" উচ্চারণ করা হয়) একটি স্ট্যান্ডার্ড ভাষা যা রিলেশনাল ডাটাবেস থেকে ডেটা পুনরুদ্ধার এবং পরিবর্তন করতে ব্যবহৃত হয়। ডেটা পুনরুদ্ধারের জন্য আপনি `SELECT` কমান্ড ব্যবহার করেন। এর মূলত, আপনি টেবিল থেকে দেখতে চান এমন কলামগুলো **select** করেন। যদি আপনি শুধুমাত্র শহরের নাম দেখাতে চান, তাহলে আপনি নিম্নলিখিত ব্যবহার করতে পারেন: ```sql SELECT city FROM cities; -- Output: -- Tokyo -- Atlanta -- Auckland ``` `SELECT` হলো যেখানে আপনি কলামগুলো তালিকাভুক্ত করেন, এবং `FROM` হলো যেখানে আপনি টেবিলগুলো তালিকাভুক্ত করেন। > [!NOTE] > SQL সিনট্যাক্স কেস-ইনসেনসিটিভ, অর্থাৎ `select` এবং `SELECT` একই অর্থ বহন করে। তবে, আপনি যে ডাটাবেস ব্যবহার করছেন তার উপর নির্ভর করে কলাম এবং টেবিলের নাম কেস-সেনসিটিভ হতে পারে। ফলস্বরূপ, প্রোগ্রামিংয়ে সবকিছু কেস-সেনসিটিভ মনে করে কাজ করাই শ্রেয়। SQL কোয়েরি লেখার সময় সাধারণ রীতি হলো কীওয়ার্ডগুলো সব বড় হাতের অক্ষরে লেখা। উপরের কোয়েরি সব শহর প্রদর্শন করবে। ধরুন আমরা শুধুমাত্র নিউজিল্যান্ডের শহরগুলো প্রদর্শন করতে চাই। আমাদের একটি ফিল্টার দরকার। SQL এর জন্য এই কীওয়ার্ড হলো `WHERE`, অর্থাৎ "যেখানে কিছু সত্য"। ```sql SELECT city FROM cities WHERE country = 'New Zealand'; -- Output: -- Auckland ``` ## ডেটা যোগ করা এখন পর্যন্ত আমরা একটি টেবিল থেকে ডেটা পুনরুদ্ধার করেছি। এখন আমরা **cities** এবং **rainfall** উভয় টেবিল থেকে ডেটা একত্রিত করতে চাই। এটি *joining* দ্বারা করা হয়। আপনি কার্যত দুই টেবিলের মধ্যে একটি সিম তৈরি করবেন, এবং প্রতিটি টেবিলের একটি কলামের মান মিলিয়ে দেবেন। আমাদের উদাহরণে, আমরা **rainfall** এর **city_id** কলামকে **cities** এর **city_id** কলামের সাথে মিলাব। এটি বৃষ্টিপাতের মানকে তার সংশ্লিষ্ট শহরের সাথে যুক্ত করবে। আমরা যে ধরনের join করব তাকে *inner* join বলা হয়, অর্থাৎ যদি কোনো সারি অন্য টেবিলের সাথে মেলে না, তবে তা প্রদর্শিত হবে না। আমাদের ক্ষেত্রে প্রতিটি শহরের বৃষ্টিপাত আছে, তাই সবকিছু প্রদর্শিত হবে। চলুন ২০১৯ সালের জন্য আমাদের সব শহরের বৃষ্টিপাত পুনরুদ্ধার করি। আমরা এটি ধাপে ধাপে করব। প্রথম ধাপ হলো ডেটা যোগ করা, যেখানে সিমের জন্য কলামগুলো নির্দেশ করা হবে - আগেই হাইলাইট করা **city_id**। ```sql SELECT cities.city rainfall.amount FROM cities INNER JOIN rainfall ON cities.city_id = rainfall.city_id ``` আমরা দুটি কলাম হাইলাইট করেছি যা আমরা চাই, এবং টেবিলগুলোকে **city_id** দ্বারা যোগ করতে চাই। এখন আমরা `WHERE` স্টেটমেন্ট যোগ করতে পারি শুধুমাত্র ২০১৯ সাল ফিল্টার করার জন্য। ```sql SELECT cities.city rainfall.amount FROM cities INNER JOIN rainfall ON cities.city_id = rainfall.city_id WHERE rainfall.year = 2019 -- Output -- city | amount -- -------- | ------ -- Tokyo | 1874 -- Atlanta | 1111 -- Auckland | 942 ``` ## সারাংশ রিলেশনাল ডাটাবেসগুলো তথ্যকে একাধিক টেবিলে ভাগ করে এবং পরে প্রদর্শন ও বিশ্লেষণের জন্য একত্রিত করে। এটি গণনা এবং ডেটা পরিচালনার জন্য উচ্চ মাত্রার নমনীয়তা প্রদান করে। আপনি একটি রিলেশনাল ডাটাবেসের মূল ধারণাগুলো এবং দুইটি টেবিলের মধ্যে join কীভাবে করতে হয় তা দেখেছেন। ## 🚀 চ্যালেঞ্জ ইন্টারনেটে অনেক রিলেশনাল ডাটাবেস উপলব্ধ আছে। আপনি উপরে শেখা দক্ষতাগুলো ব্যবহার করে ডেটা অন্বেষণ করতে পারেন। ## পোস্ট-লেকচার কুইজ ## [পোস্ট-লেকচার কুইজ](https://ff-quizzes.netlify.app/en/ds/quiz/9) ## পর্যালোচনা ও স্ব-অধ্যয়ন [Microsoft Learn](https://docs.microsoft.com/learn?WT.mc_id=academic-77958-bethanycheum) এ SQL এবং রিলেশনাল ডাটাবেস ধারণাগুলো অন্বেষণের জন্য বিভিন্ন রিসোর্স উপলব্ধ আছে - [রিলেশনাল ডেটার ধারণা বর্ণনা করুন](https://docs.microsoft.com//learn/modules/describe-concepts-of-relational-data?WT.mc_id=academic-77958-bethanycheum) - [Transact-SQL দিয়ে কোয়েরি শুরু করুন](https://docs.microsoft.com//learn/paths/get-started-querying-with-transact-sql?WT.mc_id=academic-77958-bethanycheum) (Transact-SQL হলো SQL এর একটি সংস্করণ) - [Microsoft Learn এ SQL বিষয়বস্তু](https://docs.microsoft.com/learn/browse/?products=azure-sql-database%2Csql-server&expanded=azure&WT.mc_id=academic-77958-bethanycheum) ## অ্যাসাইনমেন্ট [বিমানবন্দর ডেটা প্রদর্শন](assignment.md) --- **অস্বীকৃতি**: এই নথিটি AI অনুবাদ সেবা [Co-op Translator](https://github.com/Azure/co-op-translator) ব্যবহার করে অনূদিত হয়েছে। আমরা যথাসাধ্য সঠিকতার চেষ্টা করি, তবে স্বয়ংক্রিয় অনুবাদে ত্রুটি বা অসঙ্গতি থাকতে পারে। মূল নথিটি তার নিজস্ব ভাষায়ই কর্তৃত্বপূর্ণ উৎস হিসেবে বিবেচিত হওয়া উচিত। গুরুত্বপূর্ণ তথ্যের জন্য পেশাদার মানব অনুবাদ গ্রহণ করার পরামর্শ দেওয়া হয়। এই অনুবাদের ব্যবহারে সৃষ্ট কোনো ভুল বোঝাবুঝি বা ভুল ব্যাখ্যার জন্য আমরা দায়ী নই।