You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

195 lines
22 KiB

<!--
CO_OP_TRANSLATOR_METADATA:
{
"original_hash": "9399d7b4767e75068f95ce5c660b285c",
"translation_date": "2025-09-06T07:09:32+00:00",
"source_file": "2-Working-With-Data/05-relational-databases/README.md",
"language_code": "bn"
}
-->
# ডেটার সাথে কাজ করা: রিলেশনাল ডেটাবেস
|![ [(@sketchthedocs)](https://sketchthedocs.dev) এর স্কেচনোট ](../../sketchnotes/05-RelationalData.png)|
|:---:|
| ডেটার সাথে কাজ করা: রিলেশনাল ডেটাবেস - _[@nitya](https://twitter.com/nitya) এর স্কেচনোট_ |
সম্ভবত আপনি অতীতে তথ্য সংরক্ষণের জন্য স্প্রেডশিট ব্যবহার করেছেন। সেখানে সারি এবং কলামের একটি সেট ছিল, যেখানে সারিগুলো তথ্য (বা ডেটা) ধারণ করত এবং কলামগুলো তথ্যের বর্ণনা দিত (যাকে কখনও কখনও মেটাডেটা বলা হয়)। একটি রিলেশনাল ডেটাবেস এই মূল নীতির উপর ভিত্তি করে তৈরি হয়, যেখানে টেবিলের মধ্যে কলাম এবং সারি থাকে, যা আপনাকে একাধিক টেবিলে তথ্য ছড়িয়ে রাখতে দেয়। এটি আপনাকে আরও জটিল ডেটার সাথে কাজ করতে, পুনরাবৃত্তি এড়াতে এবং ডেটা অনুসন্ধানের ক্ষেত্রে নমনীয়তা প্রদান করে। চলুন রিলেশনাল ডেটাবেসের ধারণাগুলো অন্বেষণ করি।
## [পূর্ব-লেকচার কুইজ](https://ff-quizzes.netlify.app/en/ds/quiz/8)
## সবকিছু শুরু হয় টেবিল দিয়ে
একটি রিলেশনাল ডেটাবেসের মূল অংশ হলো টেবিল। স্প্রেডশিটের মতোই, একটি টেবিল হলো কলাম এবং সারির একটি সংগ্রহ। সারি ডেটা বা তথ্য ধারণ করে, যেমন একটি শহরের নাম বা বৃষ্টিপাতের পরিমাণ। কলামগুলো তাদের সংরক্ষিত ডেটার বর্ণনা দেয়।
চলুন শহরগুলোর তথ্য সংরক্ষণ করার জন্য একটি টেবিল তৈরি করে শুরু করি। আমরা তাদের নাম এবং দেশ দিয়ে শুরু করতে পারি। আপনি এটি একটি টেবিলে নিম্নরূপ সংরক্ষণ করতে পারেন:
| শহর | দেশ |
| -------- | ------------- |
| টোকিও | জাপান |
| আটলান্টা | যুক্তরাষ্ট্র |
| অকল্যান্ড | নিউজিল্যান্ড |
লক্ষ্য করুন **শহর**, **দেশ** এবং **জনসংখ্যা** কলামগুলো সংরক্ষিত ডেটার বর্ণনা দেয়, এবং প্রতিটি সারিতে একটি শহরের তথ্য রয়েছে।
## একটি একক টেবিল পদ্ধতির সীমাবদ্ধতা
সম্ভবত উপরের টেবিলটি আপনার কাছে বেশ পরিচিত মনে হচ্ছে। চলুন আমাদের ডেটাবেসে আরও কিছু অতিরিক্ত তথ্য যোগ করি - বার্ষিক বৃষ্টিপাত (মিলিমিটারে)। আমরা ২০১৮, ২০১৯ এবং ২০২০ সালের দিকে মনোযোগ দেব। যদি আমরা টোকিওর জন্য এটি যোগ করি, এটি নিম্নরূপ হতে পারে:
| শহর | দেশ | বছর | পরিমাণ |
| ----- | ------- | ---- | ------ |
| টোকিও | জাপান | ২০২০ | ১৬৯০ |
| টোকিও | জাপান | ২০১৯ | ১৮৭৪ |
| টোকিও | জাপান | ২০১৮ | ১৪৪৫ |
আমাদের টেবিল সম্পর্কে আপনি কী লক্ষ্য করেন? আপনি লক্ষ্য করতে পারেন যে আমরা শহরের নাম এবং দেশ বারবার পুনরাবৃত্তি করছি। এটি অনেক বেশি স্টোরেজ নিতে পারে এবং এটি মূলত অপ্রয়োজনীয়। কারণ, টোকিওর জন্য আমরা শুধুমাত্র একটি নামের তথ্য চাই।
ঠিক আছে, চলুন অন্য কিছু চেষ্টা করি। প্রতিটি বছরের জন্য নতুন কলাম যোগ করি:
| শহর | দেশ | ২০১৮ | ২০১৯ | ২০২০ |
| -------- | ------------- | ---- | ---- | ---- |
| টোকিও | জাপান | ১৪৪৫ | ১৮৭৪ | ১৬৯০ |
| আটলান্টা | যুক্তরাষ্ট্র | ১৭৭৯ | ১১১১ | ১৬৮৩ |
| অকল্যান্ড | নিউজিল্যান্ড | ১৩৮৬ | ৯৪২ | ১১৭৬ |
যদিও এটি সারির পুনরাবৃত্তি এড়ায়, এটি কয়েকটি নতুন চ্যালেঞ্জ যোগ করে। প্রতিবার নতুন বছর যোগ করার সময় আমাদের টেবিলের কাঠামো পরিবর্তন করতে হবে। এছাড়াও, আমাদের ডেটা বাড়ার সাথে সাথে বছরের কলামগুলো ব্যবহার করে মানগুলো পুনরুদ্ধার এবং গণনা করা আরও কঠিন হয়ে যাবে।
এ কারণেই আমাদের একাধিক টেবিল এবং সম্পর্কের প্রয়োজন। ডেটা ভাগ করে আমরা পুনরাবৃত্তি এড়াতে পারি এবং ডেটার সাথে কাজ করার ক্ষেত্রে আরও নমনীয়তা পেতে পারি।
## সম্পর্কের ধারণা
চলুন আমাদের ডেটায় ফিরে যাই এবং এটি কীভাবে ভাগ করা যায় তা নির্ধারণ করি। আমরা জানি যে আমরা আমাদের শহরগুলোর নাম এবং দেশ সংরক্ষণ করতে চাই, তাই এটি সম্ভবত একটি টেবিলে সবচেয়ে ভালো কাজ করবে।
| শহর | দেশ |
| -------- | ------------- |
| টোকিও | জাপান |
| আটলান্টা | যুক্তরাষ্ট্র |
| অকল্যান্ড | নিউজিল্যান্ড |
কিন্তু পরবর্তী টেবিল তৈরি করার আগে, আমাদের প্রতিটি শহরকে কীভাবে রেফারেন্স করতে হবে তা নির্ধারণ করতে হবে। আমাদের একটি আইডেন্টিফায়ার, আইডি বা (প্রযুক্তিগত ডেটাবেস পরিভাষায়) একটি প্রাইমারি কী প্রয়োজন। একটি প্রাইমারি কী হলো একটি মান যা একটি টেবিলের একটি নির্দিষ্ট সারিকে চিহ্নিত করতে ব্যবহৃত হয়। যদিও এটি একটি মানের উপর ভিত্তি করে হতে পারে (উদাহরণস্বরূপ, আমরা শহরের নাম ব্যবহার করতে পারি), এটি প্রায়শই একটি সংখ্যা বা অন্য আইডেন্টিফায়ার হওয়া উচিত। আমরা চাই না যে আইডি কখনও পরিবর্তিত হোক, কারণ এটি সম্পর্ক ভেঙে দেবে। বেশিরভাগ ক্ষেত্রে প্রাইমারি কী বা আইডি একটি স্বয়ংক্রিয়ভাবে তৈরি সংখ্যা হবে।
> ✅ প্রাইমারি কী প্রায়ই সংক্ষেপে PK বলা হয়
### শহরগুলো
| city_id | শহর | দেশ |
| ------- | -------- | ------------- |
| 1 | টোকিও | জাপান |
| 2 | আটলান্টা | যুক্তরাষ্ট্র |
| 3 | অকল্যান্ড | নিউজিল্যান্ড |
> ✅ আপনি লক্ষ্য করবেন যে আমরা এই পাঠে "id" এবং "প্রাইমারি কী" শব্দগুলো বিনিময়যোগ্যভাবে ব্যবহার করি। এই ধারণাগুলো ডেটাফ্রেমের ক্ষেত্রেও প্রযোজ্য, যা আপনি পরে অন্বেষণ করবেন। ডেটাফ্রেমগুলো "প্রাইমারি কী" পরিভাষা ব্যবহার করে না, তবে আপনি লক্ষ্য করবেন যে তারা প্রায় একইভাবে আচরণ করে।
আমাদের শহরগুলোর টেবিল তৈরি হয়ে গেলে, চলুন বৃষ্টিপাত সংরক্ষণ করি। শহরের সম্পূর্ণ তথ্য পুনরাবৃত্তি করার পরিবর্তে, আমরা আইডি ব্যবহার করতে পারি। আমরা নিশ্চিত করতে পারি যে নতুন তৈরি টেবিলেও একটি *id* কলাম রয়েছে, কারণ সব টেবিলে একটি id বা প্রাইমারি কী থাকা উচিত।
### বৃষ্টিপাত
| rainfall_id | city_id | বছর | পরিমাণ |
| ----------- | ------- | ---- | ------ |
| 1 | 1 | ২০১৮ | ১৪৪৫ |
| 2 | 1 | ২০১৯ | ১৮৭৪ |
| 3 | 1 | ২০২০ | ১৬৯০ |
| 4 | 2 | ২০১৮ | ১৭৭৯ |
| 5 | 2 | ২০১৯ | ১১১১ |
| 6 | 2 | ২০২০ | ১৬৮৩ |
| 7 | 3 | ২০১৮ | ১৩৮৬ |
| 8 | 3 | ২০১৯ | ৯৪২ |
| 9 | 3 | ২০২০ | ১১৭৬ |
লক্ষ্য করুন **city_id** কলামটি নতুন তৈরি **rainfall** টেবিলের মধ্যে রয়েছে। এই কলামটি **cities** টেবিলের আইডিগুলোকে রেফারেন্স করে। প্রযুক্তিগত রিলেশনাল ডেটা পরিভাষায়, এটিকে **ফরেন কী** বলা হয়; এটি অন্য একটি টেবিলের প্রাইমারি কী। আপনি এটিকে একটি রেফারেন্স বা পয়েন্টার হিসেবে ভাবতে পারেন। **city_id** 1 টোকিওকে রেফারেন্স করে।
> [!NOTE] ফরেন কী প্রায়ই সংক্ষেপে FK বলা হয়
## ডেটা পুনরুদ্ধার করা
আমাদের ডেটা দুটি টেবিলে ভাগ করা হয়েছে, এখন আপনি ভাবতে পারেন কীভাবে এটি পুনরুদ্ধার করা যায়। যদি আমরা MySQL, SQL Server বা Oracle-এর মতো একটি রিলেশনাল ডেটাবেস ব্যবহার করি, আমরা একটি ভাষা ব্যবহার করতে পারি যার নাম Structured Query Language বা SQL। SQL (কখনও কখনও সিকুয়েল উচ্চারণ করা হয়) একটি মানক ভাষা যা রিলেশনাল ডেটাবেসে ডেটা পুনরুদ্ধার এবং পরিবর্তন করতে ব্যবহৃত হয়।
ডেটা পুনরুদ্ধার করতে আপনি `SELECT` কমান্ড ব্যবহার করেন। এর মূল অংশ হলো, আপনি যে কলামগুলো দেখতে চান তা **select** করেন এবং যে টেবিলে তারা রয়েছে তা **from** করেন। যদি আপনি শুধুমাত্র শহরের নামগুলো প্রদর্শন করতে চান, আপনি নিম্নলিখিতটি ব্যবহার করতে পারেন:
```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** থেকে ডেটা একত্রিত করতে চাই। এটি তাদের *যোগ* করার মাধ্যমে করা হয়। আপনি কার্যত দুটি টেবিলের মধ্যে একটি সিম তৈরি করবেন এবং প্রতিটি টেবিলের একটি কলাম থেকে মানগুলো মেলাবেন।
আমাদের উদাহরণে, আমরা **rainfall**-এর **city_id** কলামকে **cities**-এর **city_id** কলামের সাথে মেলাব। এটি বৃষ্টিপাতের মানকে তার সংশ্লিষ্ট শহরের সাথে মেলাবে। আমরা যে যোগটি করব তা হলো একটি *ইনার* যোগ, অর্থাৎ যদি কোনো সারি অন্য টেবিলের কিছু মেলাতে না পারে তবে তা প্রদর্শিত হবে না। আমাদের ক্ষেত্রে প্রতিটি শহরের বৃষ্টিপাত রয়েছে, তাই সবকিছু প্রদর্শিত হবে।
চলুন ২০১৯ সালের বৃষ্টিপাত আমাদের সব শহরের জন্য পুনরুদ্ধার করি।
আমরা এটি ধাপে ধাপে করব। প্রথম ধাপ হলো ডেটা একত্রিত করা, যেখানে আমরা সিমের জন্য কলামগুলো নির্দেশ করব - **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
```
## সারসংক্ষেপ
রিলেশনাল ডেটাবেসের মূল ধারণা হলো তথ্যকে একাধিক টেবিলে ভাগ করা, যা পরে প্রদর্শন এবং বিশ্লেষণের জন্য একত্রিত করা হয়। এটি গণনা এবং ডেটা পরিচালনা করার ক্ষেত্রে উচ্চ মাত্রার নমনীয়তা প্রদান করে। আপনি একটি রিলেশনাল ডেটাবেসের মূল ধারণাগুলো এবং দুটি টেবিলের মধ্যে যোগ করার পদ্ধতি দেখেছেন।
## 🚀 চ্যালেঞ্জ
ইন্টারনেটে অসংখ্য রিলেশনাল ডেটাবেস উপলব্ধ রয়েছে। আপনি উপরের শেখা দক্ষতাগুলো ব্যবহার করে ডেটা অন্বেষণ করতে পারেন।
## পোস্ট-লেকচার কুইজ
## [পোস্ট-লেকচার কুইজ](https://ff-quizzes.netlify.app/en/ds/quiz/9)
## পর্যালোচনা ও স্ব-অধ্যয়ন
SQL এবং রিলেশনাল ডেটাবেসের ধারণাগুলো অন্বেষণ করার জন্য [Microsoft Learn](https://docs.microsoft.com/learn?WT.mc_id=academic-77958-bethanycheum)-এ বেশ কয়েকটি রিসোর্স উপলব্ধ রয়েছে
- [রিলেশনাল ডেটার ধারণাগুলো বর্ণনা করুন](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) ব্যবহার করে অনুবাদ করা হয়েছে। আমরা যথাসম্ভব সঠিক অনুবাদ প্রদানের চেষ্টা করি, তবে অনুগ্রহ করে মনে রাখবেন যে স্বয়ংক্রিয় অনুবাদে ত্রুটি বা অসঙ্গতি থাকতে পারে। মূল ভাষায় থাকা নথিটিকে প্রামাণিক উৎস হিসেবে বিবেচনা করা উচিত। গুরুত্বপূর্ণ তথ্যের জন্য, পেশাদার মানব অনুবাদ সুপারিশ করা হয়। এই অনুবাদ ব্যবহারের ফলে কোনো ভুল বোঝাবুঝি বা ভুল ব্যাখ্যা হলে আমরা দায়বদ্ধ থাকব না।