mysql - একাধিক সারণী থেকে এসকিউএল প্রশ্ন ফিরে তথ্য
select (4)
আমি নিম্নলিখিত জানতে চাই
- কিভাবে আমার ডাটাবেস একাধিক টেবিল থেকে তথ্য পেতে?
- এটা কি ধরনের পদ্ধতি আছে?
- যোগদান এবং ইউনিয়ন কি এবং কিভাবে তারা একে অপরের থেকে পৃথক?
- আমি অন্যদের তুলনায় প্রতিটি এক ব্যবহার করা উচিত?
আমি এটিকে আমার (উদাহরণস্বরূপ - পিএইচপি) অ্যাপ্লিকেশনটিতে ব্যবহার করার পরিকল্পনা করছি, তবে ডাটাবেসের বিরুদ্ধে একাধিক প্রশ্ন চালাতে চাই না, একক প্রশ্নের মধ্যে একাধিক সারণিতে ডেটা পেতে আমার কোন বিকল্পগুলি আছে?
দ্রষ্টব্য: আমি এটি লিখছি কারণ আমি ক্রমাগত পিএইচপি সারিতে যাচ্ছি এমন অসংখ্য প্রশ্নগুলির উপর একটি ভাল লিখিত গাইড লিঙ্ক করতে সক্ষম হতে চাই, তাই আমি যখন উত্তরটি পোস্ট করব তখন আরও বিস্তারিত জানার জন্য আমি এই লিঙ্কটি লিঙ্ক করতে পারি।
উত্তর নিম্নলিখিত কভার আবরণ:
- অংশ 1 - যোগদান এবং ইউনিয়ন
- পার্ট 2 - Subqueries
- পার্ট 3 - কৌশল এবং দক্ষ কোড
- অংশ 4 - দফা থেকে সাবকোয়ারি
- পার্ট 5 - জন এর ঠাট মিশ্রিত ব্যাগ
অংশ 1 - যোগদান এবং ইউনিয়ন
এই উত্তর কভার:
- অংশ 1
- একটি অভ্যন্তরীণ যোগদান ব্যবহার করে দুই বা তার বেশি টেবিল যোগদান (অতিরিক্ত তথ্যের জন্য উইকিপিডিয়া এন্ট্রি দেখুন)
- একটি ইউনিয়ন প্রশ্নের ব্যবহার কিভাবে
- বাম এবং ডান বাইরের যোগদান করে (এই স্ট্যাক ওভারফ্লো উত্তর যোগদানের ধরন বর্ণনা করার জন্য চমৎকার)
- অন্তর্ভূক্ত প্রশ্নগুলি (এবং আপনার ডাটাবেস তাদের সমর্থন না করলে তাদের পুনরুত্পাদন কিভাবে করবেন) - এটি SQL- সার্ভারের একটি ফাংশন ( তথ্য দেখুন ) এবং আমি এই পুরো জিনিসটিকে প্রথম স্থানে লেখার কারণের অংশ।
- অংশ ২
- Subqueries - তারা কি, যেখানে তারা ব্যবহার করা যেতে পারে এবং কি জন্য নজর রাখা
- Cartesian AKA যোগদান - ওহ, দুঃখ!
একটি ডাটাবেস একাধিক টেবিল থেকে তথ্য উদ্ধার করার উপায় আছে। এই উত্তরে, আমি ANSI-92 ব্যবহার সিনট্যাক্স ব্যবহার করা হবে। এটি পুরোনো ANSI-89 সিনট্যাক্স ব্যবহার করে এমন অনেক অন্যান্য টিউটোরিয়ালের জন্য আলাদা হতে পারে (এবং যদি আপনি 89 তে ব্যবহার করেন তবে খুব কম স্বজ্ঞাত মনে হতে পারে - তবে আমি এটি বলতে চেষ্টা করতে পারি) এটি অনেক সহজ প্রশ্নের আরো জটিল পেয়ে শুরু করার সময় বুঝতে। কেন এটা ব্যবহার করবেন? একটি কর্মক্ষমতা লাভ আছে? সংক্ষিপ্ত উত্তর নেই, তবে আপনি এটি ব্যবহার করতে একবার পড়তে সহজ। এই সিনট্যাক্স ব্যবহার করে অন্য লোকেরা লিখেছেন এমন প্রশ্নগুলি পড়ার পক্ষে সহজ।
আমি একটি ছোট ক্যারাড্ডের ধারণাটি ব্যবহার করতে যাচ্ছি যা তার কাছে কোন গাড়িগুলি উপলব্ধ আছে তা নজর রাখতে ডেটাবেস রয়েছে। মালিকটি আপনাকে তার আইটি কম্পিউটারের লোক হিসাবে ভাড়া দিয়েছেন এবং আশা করেন যে আপনি হ্যাটের ড্রপে তার জন্য যে তথ্যটি চান সেটি হ্রাস করতে পারবেন।
আমি বেশ কয়েকটি অনুসন্ধান টেবিল তৈরি করেছি যা চূড়ান্ত টেবিলে ব্যবহার করা হবে। এটি আমাদের থেকে একটি যুক্তিসঙ্গত মডেল দিতে হবে। শুরু করার জন্য, আমি নিম্নোক্ত কাঠামোর উদাহরণস্বরূপ একটি উদাহরণ ডাটাবেসের বিরুদ্ধে আমার প্রশ্নগুলি চালাচ্ছি। আমি যখন শুরু করি এবং তাদের সাথে কী ভুল হয় তা ব্যাখ্যা করার জন্য তৈরি করা সাধারণ ভুলগুলি মনে করার চেষ্টা করব - পাশাপাশি অবশ্যই কীভাবে তাদের সংশোধন করা হয় তা দেখানো হবে।
প্রথম টেবিলটি কেবল একটি রঙের তালিকা যাতে আমরা জানি যে গাড়ির গজায় আমাদের কোন রং আছে।
mysql> create table colors(id int(3) not null auto_increment primary key,
-> color varchar(15), paint varchar(10));
Query OK, 0 rows affected (0.01 sec)
mysql> show columns from colors;
+-------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+----------------+
| id | int(3) | NO | PRI | NULL | auto_increment |
| color | varchar(15) | YES | | NULL | |
| paint | varchar(10) | YES | | NULL | |
+-------+-------------+------+-----+---------+----------------+
3 rows in set (0.01 sec)
mysql> insert into colors (color, paint) values ('Red', 'Metallic'),
-> ('Green', 'Gloss'), ('Blue', 'Metallic'),
-> ('White' 'Gloss'), ('Black' 'Gloss');
Query OK, 5 rows affected (0.00 sec)
Records: 5 Duplicates: 0 Warnings: 0
mysql> select * from colors;
+----+-------+----------+
| id | color | paint |
+----+-------+----------+
| 1 | Red | Metallic |
| 2 | Green | Gloss |
| 3 | Blue | Metallic |
| 4 | White | Gloss |
| 5 | Black | Gloss |
+----+-------+----------+
5 rows in set (0.00 sec)
ব্র্যান্ডের টেবিলটি কারার বিভিন্ন ব্রান্ডের শনাক্ত করে যা সম্ভবত ক্যারিয়ারটি বিক্রি করতে পারে।
mysql> create table brands (id int(3) not null auto_increment primary key,
-> brand varchar(15));
Query OK, 0 rows affected (0.01 sec)
mysql> show columns from brands;
+-------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+----------------+
| id | int(3) | NO | PRI | NULL | auto_increment |
| brand | varchar(15) | YES | | NULL | |
+-------+-------------+------+-----+---------+----------------+
2 rows in set (0.01 sec)
mysql> insert into brands (brand) values ('Ford'), ('Toyota'),
-> ('Nissan'), ('Smart'), ('BMW');
Query OK, 5 rows affected (0.00 sec)
Records: 5 Duplicates: 0 Warnings: 0
mysql> select * from brands;
+----+--------+
| id | brand |
+----+--------+
| 1 | Ford |
| 2 | Toyota |
| 3 | Nissan |
| 4 | Smart |
| 5 | BMW |
+----+--------+
5 rows in set (0.00 sec)
মডেল টেবিলটি বিভিন্ন ধরণের গাড়িগুলি ঢেকে রাখবে, এটি আসল কার মডেলগুলির পরিবর্তে বিভিন্ন গাড়ির ধরনগুলি ব্যবহার করা সহজ হবে।
mysql> create table models (id int(3) not null auto_increment primary key,
-> model varchar(15));
Query OK, 0 rows affected (0.01 sec)
mysql> show columns from models;
+-------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+----------------+
| id | int(3) | NO | PRI | NULL | auto_increment |
| model | varchar(15) | YES | | NULL | |
+-------+-------------+------+-----+---------+----------------+
2 rows in set (0.00 sec)
mysql> insert into models (model) values ('Sports'), ('Sedan'), ('4WD'), ('Luxury');
Query OK, 4 rows affected (0.00 sec)
Records: 4 Duplicates: 0 Warnings: 0
mysql> select * from models;
+----+--------+
| id | model |
+----+--------+
| 1 | Sports |
| 2 | Sedan |
| 3 | 4WD |
| 4 | Luxury |
+----+--------+
4 rows in set (0.00 sec)
এবং অবশেষে, এই সমস্ত টেবিলগুলি একত্রিত করার জন্য, টেবিল যা একসঙ্গে একসাথে থাকে। আইডি ক্ষেত্র আসলে গাড়ি সনাক্ত করতে ব্যবহৃত অনন্য লট সংখ্যা।
mysql> create table cars (id int(3) not null auto_increment primary key,
-> color int(3), brand int(3), model int(3));
Query OK, 0 rows affected (0.01 sec)
mysql> show columns from cars;
+-------+--------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+--------+------+-----+---------+----------------+
| id | int(3) | NO | PRI | NULL | auto_increment |
| color | int(3) | YES | | NULL | |
| brand | int(3) | YES | | NULL | |
| model | int(3) | YES | | NULL | |
+-------+--------+------+-----+---------+----------------+
4 rows in set (0.00 sec)
mysql> insert into cars (color, brand, model) values (1,2,1), (3,1,2), (5,3,1),
-> (4,4,2), (2,2,3), (3,5,4), (4,1,3), (2,2,1), (5,2,3), (4,5,1);
Query OK, 10 rows affected (0.00 sec)
Records: 10 Duplicates: 0 Warnings: 0
mysql> select * from cars;
+----+-------+-------+-------+
| id | color | brand | model |
+----+-------+-------+-------+
| 1 | 1 | 2 | 1 |
| 2 | 3 | 1 | 2 |
| 3 | 5 | 3 | 1 |
| 4 | 4 | 4 | 2 |
| 5 | 2 | 2 | 3 |
| 6 | 3 | 5 | 4 |
| 7 | 4 | 1 | 3 |
| 8 | 2 | 2 | 1 |
| 9 | 5 | 2 | 3 |
| 10 | 4 | 5 | 1 |
+----+-------+-------+-------+
10 rows in set (0.00 sec)
এটি আমাদের যথেষ্ট তথ্য সরবরাহ করবে (আমি আশা করি) বিভিন্ন ধরনের যোগদানের নীচের উদাহরণগুলিকে কভার করে এবং যথাযথ করে তুলতে যথেষ্ট ডেটা দেবে।
সুতরাং এটি আঁকা মধ্যে, বস তার সব ক্রীড়া গাড়ির আইডি জানতে চান।
এটি একটি সহজ দুই টেবিল যোগদান। আমরা একটি টেবিল আছে যা মডেল এবং টেবিলের উপলব্ধ স্টক দিয়ে চিহ্নিত করে। আপনি যেমন দেখতে পারেন, cars
টেবিলের model
কলামের ডেটা আমাদের কাছে থাকা cars
টেবিলের models
কলামের সাথে সম্পর্কিত। এখন, আমরা জানি যে মডেলের টেবিলে Sports
জন্য একটি আইডি আছে তাই যোগদান লিখুন।
select
ID,
model
from
cars
join models
on model=ID
তাই এই প্রশ্নের সঠিক অধিকার দেখায়? আমরা দুটি টেবিল চিহ্নিত করেছি এবং আমাদের প্রয়োজনীয় তথ্য রয়েছে এবং একটি কলাম ব্যবহার করে যা কলামে যোগদান করতে সঠিকভাবে চিহ্নিত করে।
ERROR 1052 (23000): Column 'ID' in field list is ambiguous
ওহ না! আমাদের প্রথম প্রশ্নের একটি ত্রুটি! হ্যাঁ, এবং এটি একটি কলম। আপনি দেখুন, প্রশ্নটি প্রকৃতপক্ষে সঠিক কলাম পেয়েছে, তবে তাদের মধ্যে কয়েকজনই উভয় টেবিলের মধ্যে বিদ্যমান, সুতরাং ডাটাবেসটি কী প্রকৃত কলামের আমাদের অর্থ এবং কোথায় সে সম্পর্কে বিভ্রান্ত হয়। এই সমাধান দুটি সমাধান আছে। প্রথমটি হল চমৎকার এবং সহজ, আমরা ডাটাবেসকে ঠিক যেমন বলতে চাই তা বলতে tableName.columnName
ব্যবহার করতে পারি:
select
cars.ID,
models.model
from
cars
join models
on cars.model=models.ID
+----+--------+
| ID | model |
+----+--------+
| 1 | Sports |
| 3 | Sports |
| 8 | Sports |
| 10 | Sports |
| 2 | Sedan |
| 4 | Sedan |
| 5 | 4WD |
| 7 | 4WD |
| 9 | 4WD |
| 6 | Luxury |
+----+--------+
10 rows in set (0.00 sec)
অন্য সম্ভবত সম্ভবত ব্যবহৃত হয় এবং টেবিল আলাইজিং বলা হয়। এই উদাহরণের টেবিলে চমৎকার এবং ছোট সহজ নাম রয়েছে, তবে KPI_DAILY_SALES_BY_DEPARTMENT
মত কিছু টাইপ করা সম্ভবত পুরানো হয়ে যাবে, তাই একটি সহজ পদ্ধতি হল টেবিলটির ডাকনামটি এইভাবে নামকরণ করা:
select
a.ID,
b.model
from
cars a
join models b
on a.model=b.ID
এখন, অনুরোধ ফিরে। আমরা দেখতে পাচ্ছি যে আমাদের কাছে প্রয়োজনীয় তথ্য রয়েছে, কিন্তু আমাদেরও এমন তথ্য রয়েছে যা জিজ্ঞাসা করা হয়নি, তাই বিবৃতিতে কোন বিভাগে কেবলমাত্র স্পোর্টস গাড়িগুলি জিজ্ঞাসা করার জন্য আমাদের এই বিভাগটি অন্তর্ভুক্ত করতে হবে। আমি টেবিলের নামগুলি ওভার ওভার ব্যবহার করার পরিবর্তে টেবিল ওরফে পদ্ধতিটি পছন্দ করি, আমি এই বিন্দু থেকে পরে এটি আটকে রাখব।
স্পষ্টতই, আমাদের ক্যোয়ারিতে কোন বিভাগ যোগ করতে হবে। আমরা ID=1
বা model='Sports'
দ্বারা স্পোর্টস গাড়িগুলি সনাক্ত করতে পারি। হিসাবে আইডি সূচী এবং প্রাথমিক কী (এবং এটি কম টাইপ করা হবে), আমাদের প্রশ্নের মধ্যে যে ব্যবহার করতে দেয়।
select
a.ID,
b.model
from
cars a
join models b
on a.model=b.ID
where
b.ID=1
+----+--------+
| ID | model |
+----+--------+
| 1 | Sports |
| 3 | Sports |
| 8 | Sports |
| 10 | Sports |
+----+--------+
4 rows in set (0.00 sec)
বিঙ্গো! বস খুশি। অবশ্যই, একজন মনিব হওয়া এবং তিনি যা চেয়েছিলেন তার সাথে সুখী হবেন না, তিনি তথ্যটি দেখেন, তারপর বলেন যে আমিও রং চাই ।
ঠিক আছে, তাই আমাদের ইতিমধ্যে আমাদের লিখিত প্রশ্নগুলির একটি ভাল অংশ আছে, তবে আমাদের রঙের একটি তৃতীয় টেবিল ব্যবহার করতে হবে। এখন, আমাদের প্রধান তথ্য টেবিলের cars
গাড়ি রঙ আইডি সংরক্ষণ করে এবং এই লিঙ্কগুলির রং আইডি কলামে ফিরে আসে। সুতরাং, আসল ভাবে একইভাবে, আমরা একটি তৃতীয় টেবিলে যোগ দিতে পারি:
select
a.ID,
b.model
from
cars a
join models b
on a.model=b.ID
join colors c
on a.color=c.ID
where
b.ID=1
+----+--------+
| ID | model |
+----+--------+
| 1 | Sports |
| 3 | Sports |
| 8 | Sports |
| 10 | Sports |
+----+--------+
4 rows in set (0.00 sec)
যদিও, টেবিলটি সঠিকভাবে যোগদান করা হয়েছিল এবং সম্পর্কিত কলামগুলি লিঙ্কযুক্ত ছিল, আমরা কেবলমাত্র লিঙ্কযুক্ত নতুন টেবিলের প্রকৃত তথ্যটি টেনে আনতে ভুলে গেছি।
select
a.ID,
b.model,
c.color
from
cars a
join models b
on a.model=b.ID
join colors c
on a.color=c.ID
where
b.ID=1
+----+--------+-------+
| ID | model | color |
+----+--------+-------+
| 1 | Sports | Red |
| 8 | Sports | Green |
| 10 | Sports | White |
| 3 | Sports | Black |
+----+--------+-------+
4 rows in set (0.00 sec)
ঠিক আছে, এক মুহুর্তের জন্য আমাদের পিঠ বন্ধ করে দিয়েছে। এখন, একটু বিস্তারিতভাবে এই কিছু ব্যাখ্যা করতে। আপনি দেখতে পারেন যে, আমাদের বিবৃতিতে from
অনুচ্ছেদটি আমাদের প্রধান টেবিলের সাথে লিঙ্ক করে (আমি প্রায়ই একটি টেবিল ব্যবহার করি যা অনুসন্ধান বা মাত্রা টেবিলের পরিবর্তে তথ্য ধারণ করে। ক্যোয়ারীটি কেবলমাত্র যে সমস্ত টেবিলের চারপাশে স্যুইচ করা হয়েছে তার সাথেও কাজ করবে তবে কম অর্থে যখন আমরা কয়েক মাসের মধ্যে এটি পড়তে এই প্রশ্নের সাথে ফিরে আসি, তখন এটি একটি ভাল প্রশ্ন যা লিখতে ভাল এবং সহজে বোঝার চেষ্টা করা ভাল। এটি সহজভাবে লিখুন, সুন্দর ইন্ডেন্ট ব্যবহার করুন যাতে সবকিছু পরিষ্কার হয় যেমনটি হতে পারে। যদি আপনি অন্যকে শেখানোর জন্য যান তবে এই বৈশিষ্ট্যগুলিকে তাদের প্রশ্নগুলিতে উত্থাপন করার চেষ্টা করুন - বিশেষ করে যদি আপনি তাদের সমস্যা সমাধান করতে পারেন।
এই পদ্ধতিতে আরো এবং আরো টেবিল লিঙ্ক রাখা সম্পূর্ণরূপে সম্ভব।
select
a.ID,
b.model,
c.color
from
cars a
join models b
on a.model=b.ID
join colors c
on a.color=c.ID
join brands d
on a.brand=d.ID
where
b.ID=1
আমি একটি টেবিল অন্তর্ভুক্ত করতে ভুলে গেছি যেখানে আমরা join
বিবৃতিতে একাধিক কলামে যোগদান করতে চাইতে পারি, এখানে একটি উদাহরণ। যদি models
টেবিলে ব্র্যান্ড-নির্দিষ্ট মডেল থাকে এবং সেইসাথে brand
নামক একটি কলাম থাকে যা ID
ক্ষেত্রের brands
টেবিলের সাথে লিঙ্কযুক্ত থাকে তবে এটি এইভাবে করা যেতে পারে:
select
a.ID,
b.model,
c.color
from
cars a
join models b
on a.model=b.ID
join colors c
on a.color=c.ID
join brands d
on a.brand=d.ID
and b.brand=d.ID
where
b.ID=1
আপনি দেখতে পারেন, উপরে দেওয়া প্রশ্নটি কেবল সংযুক্ত টেবিলগুলিকে মূল cars
সারণিতে লিঙ্ক করে না, তবে ইতিমধ্যে যোগদানকৃত সারণির মধ্যে যোগদান করে। যদি এটি করা না হয়, ফলাফলটি কার্টেসিয়ান যোগদান করা হয় - যা ডিবাটি খারাপ বলে কথা বলে। একটি কার্টেসিয়ান যোগদান এক যেখানে সারিগুলি ফেরত দেওয়া হয় কারণ তথ্যগুলি সীমাবদ্ধতা কিভাবে সীমাবদ্ধ করে তা ডাটাবেসকে বলে না, তাই প্রশ্নটি মাপদণ্ডের সাথে মেলে এমন সমস্ত সারি ফেরত দেয়।
সুতরাং, একটি কার্টিজিয়ান যোগদান একটি উদাহরণ দিতে, নিম্নলিখিত প্রশ্নের চালানো যাক:
select
a.ID,
b.model
from
cars a
join models b
+----+--------+
| ID | model |
+----+--------+
| 1 | Sports |
| 1 | Sedan |
| 1 | 4WD |
| 1 | Luxury |
| 2 | Sports |
| 2 | Sedan |
| 2 | 4WD |
| 2 | Luxury |
| 3 | Sports |
| 3 | Sedan |
| 3 | 4WD |
| 3 | Luxury |
| 4 | Sports |
| 4 | Sedan |
| 4 | 4WD |
| 4 | Luxury |
| 5 | Sports |
| 5 | Sedan |
| 5 | 4WD |
| 5 | Luxury |
| 6 | Sports |
| 6 | Sedan |
| 6 | 4WD |
| 6 | Luxury |
| 7 | Sports |
| 7 | Sedan |
| 7 | 4WD |
| 7 | Luxury |
| 8 | Sports |
| 8 | Sedan |
| 8 | 4WD |
| 8 | Luxury |
| 9 | Sports |
| 9 | Sedan |
| 9 | 4WD |
| 9 | Luxury |
| 10 | Sports |
| 10 | Sedan |
| 10 | 4WD |
| 10 | Luxury |
+----+--------+
40 rows in set (0.00 sec)
ভাল ঈশ্বর, যে কুশ্রী। যাইহোক, যতক্ষণ ডাটাবেস উদ্বিগ্ন, এটি ঠিক কি জিজ্ঞাসা করা হয়। প্রশ্নের জবাবে, আমরা model
থেকে models
এবং model
থেকে ID
জন্য জিজ্ঞাসা। যাইহোক, যেহেতু আমরা টেবিলের সাথে যোগদান করতে নির্দিষ্ট করে নিই না, তাই ডাটাবেজটি দ্বিতীয় সারণির প্রতিটি সারির সাথে প্রথম সারণির প্রতিটি সারির সাথে মেলে।
ঠিক আছে, তাই বস ফিরে এসেছে, এবং সে আবার আরও তথ্য চায়। আমি একই তালিকা চান, কিন্তু এটি 4WDs অন্তর্ভুক্ত ।
এই, যদিও, এই অর্জন করার দুটি ভিন্ন উপায়ে তাকান আমাদের একটি মহান অজুহাত দেয়। আমরা এই ধরনের ধারা যেখানে অন্য শর্ত যোগ করতে পারে:
select
a.ID,
b.model,
c.color
from
cars a
join models b
on a.model=b.ID
join colors c
on a.color=c.ID
join brands d
on a.brand=d.ID
where
b.ID=1
or b.ID=3
যদিও উপরের কাজটি পুরোপুরি ভালভাবে কাজ করবে, তবে এটিকে আলাদাভাবে দেখায়, এটি কীভাবে একটি union
ক্যোয়ারী কাজ করবে তা দেখানোর জন্য একটি দুর্দান্ত অজুহাত।
আমরা জানি যে নিম্নলিখিত সমস্ত স্পোর্টস গাড়ি ফেরত দেবে:
select
a.ID,
b.model,
c.color
from
cars a
join models b
on a.model=b.ID
join colors c
on a.color=c.ID
join brands d
on a.brand=d.ID
where
b.ID=1
এবং নিম্নলিখিত সব 4WDs ফিরে হবে:
select
a.ID,
b.model,
c.color
from
cars a
join models b
on a.model=b.ID
join colors c
on a.color=c.ID
join brands d
on a.brand=d.ID
where
b.ID=3
সুতরাং একটি union all
যুক্ত করে তাদের মধ্যে union all
, দ্বিতীয় প্রশ্নের ফলাফল প্রথম প্রশ্নের ফলাফল যোগ করা হবে।
select
a.ID,
b.model,
c.color
from
cars a
join models b
on a.model=b.ID
join colors c
on a.color=c.ID
join brands d
on a.brand=d.ID
where
b.ID=1
union all
select
a.ID,
b.model,
c.color
from
cars a
join models b
on a.model=b.ID
join colors c
on a.color=c.ID
join brands d
on a.brand=d.ID
where
b.ID=3
+----+--------+-------+
| ID | model | color |
+----+--------+-------+
| 1 | Sports | Red |
| 8 | Sports | Green |
| 10 | Sports | White |
| 3 | Sports | Black |
| 5 | 4WD | Green |
| 7 | 4WD | White |
| 9 | 4WD | Black |
+----+--------+-------+
7 rows in set (0.00 sec)
আপনি দেখতে পারেন, প্রথম প্রশ্নের ফলাফল প্রথমে ফেরত পাঠানো হয়, দ্বিতীয় প্রশ্নের ফলাফল অনুসরণ করে।
এই উদাহরণে, অবশ্যই প্রথম প্রশ্নের উত্তরটি ব্যবহার করা অনেক সহজ ছিল, তবে নির্দিষ্ট ক্ষেত্রেই union
প্রশ্নগুলি দুর্দান্ত হতে পারে। তারা সারণী থেকে টেবিলগুলির কাছ থেকে নির্দিষ্ট ফলাফলগুলি ফেরত দেওয়ার একটি দুর্দান্ত উপায় যা সহজে একত্রে যোগদান করা হয় না - অথবা সেই বিষয়টি সম্পূর্ণভাবে সম্পর্কিত নয়। তবে অনুসরণ করার জন্য কয়েকটি নিয়ম আছে।
- প্রথম প্রশ্নের থেকে কলামের ধরনগুলি নীচের প্রতিটি ক্যোয়ারী থেকে কলামের ধরনগুলির সাথে মেলে।
- প্রথম প্রশ্নের থেকে কলামের নামগুলি সমগ্র সেট ফলাফল সনাক্ত করতে ব্যবহার করা হবে।
- প্রতিটি প্রশ্নের মধ্যে কলাম সংখ্যা একই হতে হবে।
এখন, আপনি হয়তো ভাবছেন যে union
ও union all
ব্যবহার করার মধ্যে পার্থক্য কী? একটি union
প্রশ্নের সদৃশ মুছে ফেলা হবে, যখন একটি union all
হবে না। এর মানে এই যে union
সংঘটিত union all
ব্যবহার করার সময় একটি ছোট পারফরম্যান্স আঘাত হ'ল কিন্তু এর ফলাফলগুলি মূল্যবান হতে পারে - যদিও আমি এই ধরণের জিনিসটি ভাবাব না।
এই নোটে, এখানে কিছু অতিরিক্ত নোট উল্লেখযোগ্য হতে পারে।
- যদি আমরা ফলাফলগুলি অর্ডার করতে চাই, আমরা একটি
order by
ব্যবহার করতে পারি তবে আপনি এখন ওরফে ব্যবহার করতে পারবেন না। উপরের প্রশ্নের মধ্যে,order by a.ID
একটিorder by a.ID
যোগ করা একটি ত্রুটি হতে পারে - যতদূর ফলাফল সম্পর্কিত হয়, কলামটিকেa.ID
-এর পরিবর্তেID
বলা হয় - যদিও একই উপনাম উভয় প্রশ্নের মধ্যে ব্যবহার করা হয়েছে। - আমরা বিবৃতি
order by
শুধুমাত্র একটিorder by
থাকতে পারে, এবং এটি শেষ বিবৃতি হিসাবে হতে হবে।
পরবর্তী উদাহরণের জন্য, আমি আমাদের টেবিলে কয়েকটি অতিরিক্ত সারি যোগ করছি।
আমি ব্রান্ডের টেবিলে Holden
যোগ করেছি। আমি 12
এর color
মান সহ cars
একটি সারি যুক্ত করেছি - যা রং টেবিলে কোন উল্লেখ নেই।
ঠিক আছে, বস আবার ফিরে আসে, অনুরোধগুলি ভঙ্গ করে - * আমি আমাদের প্রতিটি ব্র্যান্ডের সংখ্যা এবং এটিতে গাড়িগুলির সংখ্যা গণনা করতে চাই! '- সাধারণত, আমরা আমাদের আলোচনার একটি মজার অংশে পৌঁছাতে চাই এবং বস আরো কাজ করতে চায়। ।
ঠিক আছে, তাই আমাদের যা করতে হবে তা হল প্রথম ব্র্যান্ডের সম্পূর্ণ তালিকা পেতে।
select
a.brand
from
brands a
+--------+
| brand |
+--------+
| Ford |
| Toyota |
| Nissan |
| Smart |
| BMW |
| Holden |
+--------+
6 rows in set (0.00 sec)
এখন, যখন আমরা আমাদের গাড়ির টেবিলে যোগদান করি তখন আমরা নিম্নলিখিত ফলাফলটি পাই:
select
a.brand
from
brands a
join cars b
on a.ID=b.brand
group by
a.brand
+--------+
| brand |
+--------+
| BMW |
| Ford |
| Nissan |
| Smart |
| Toyota |
+--------+
5 rows in set (0.00 sec)
যা অবশ্যই একটি সমস্যা - আমি যোগ করা সুদৃশ্য Holden
ব্র্যান্ড কোন উল্লেখ দেখছি না।
কারণ একটি যোগদান উভয় সারণিতে মেলা সারির জন্য দেখায়। যেহেতু গাড়ির কোনও তথ্য নেই Holden
এটি ফেরত দেওয়া হয় না। এই যেখানে আমরা একটি outer
যোগদান ব্যবহার করতে পারেন। এটি অন্য টেবিলের সাথে মিলেছে কিনা তা এক টেবিল থেকে সমস্ত ফলাফল ফিরিয়ে দেবে:
select
a.brand
from
brands a
left outer join cars b
on a.ID=b.brand
group by
a.brand
+--------+
| brand |
+--------+
| BMW |
| Ford |
| Holden |
| Nissan |
| Smart |
| Toyota |
+--------+
6 rows in set (0.00 sec)
এখন আমরা যে আছে, আমরা একটি গণনা পেতে একটি সুদৃশ্য সামগ্রিক ফাংশন যোগ করতে পারেন এবং একটি মুহূর্ত জন্য আমাদের পিঠ বন্ধ বস পেতে পারেন।
select
a.brand,
count(b.id) as countOfBrand
from
brands a
left outer join cars b
on a.ID=b.brand
group by
a.brand
+--------+--------------+
| brand | countOfBrand |
+--------+--------------+
| BMW | 2 |
| Ford | 2 |
| Holden | 0 |
| Nissan | 1 |
| Smart | 1 |
| Toyota | 5 |
+--------+--------------+
6 rows in set (0.00 sec)
এবং যে সঙ্গে, বস skulks দূরে।
এখন, কিছু বিস্তারিতভাবে এই ব্যাখ্যা করার জন্য, বাহ্যিক যোগ left
বা right
টাইপ হতে পারে। বাম বা ডানটি কোন টেবিলের সম্পূর্ণরূপে অন্তর্ভুক্ত করা হয়েছে তা সংজ্ঞায়িত করে। left outer join
টেবিল থেকে সমস্ত সারি অন্তর্ভুক্ত করা হবে, (যখন আপনি এটি অনুমান করেছিলেন) একটি right outer join
ফলাফলের মধ্যে ডান দিকে টেবিল থেকে সমস্ত ফলাফল নিয়ে আসে।
কিছু ডাটাবেস একটি full outer join
অনুমতি দেয় যা উভয় সারণিতে ফলাফলগুলি ( উভয় মিলিত বা না) আনবে, তবে এটি সমস্ত ডেটাবেসে সমর্থিত নয়।
এখন, আমি সম্ভবত এই মুহুর্তে চিত্রিত, আপনি একটি প্রশ্নে যোগদানের ধরনগুলি একত্রিত করতে পারেন কিনা তা নিয়ে ভাবছেন - এবং উত্তর হল হ্যাঁ, আপনি একেবারেই করতে পারেন।
select
b.brand,
c.color,
count(a.id) as countOfBrand
from
cars a
right outer join brands b
on b.ID=a.brand
join colors c
on a.color=c.ID
group by
a.brand,
c.color
+--------+-------+--------------+
| brand | color | countOfBrand |
+--------+-------+--------------+
| Ford | Blue | 1 |
| Ford | White | 1 |
| Toyota | Black | 1 |
| Toyota | Green | 2 |
| Toyota | Red | 1 |
| Nissan | Black | 1 |
| Smart | White | 1 |
| BMW | Blue | 1 |
| BMW | White | 1 |
+--------+-------+--------------+
9 rows in set (0.00 sec)
সুতরাং, কেন যে ফলাফল আশা করা হয় না? কারণ আমরা কার থেকে ব্র্যান্ডগুলিতে বাইরের যোগদানটি বেছে নিলেও এটি রংগুলিতে যোগ দেওয়ার জন্য নির্দিষ্ট করা হয়নি - যাতে বিশেষ যোগদান কেবল উভয় টেবিলের সাথে মেলে এমন ফলাফলগুলি ফিরিয়ে আনবে।
এখানে এমন প্রশ্ন রয়েছে যা আমরা আশা করি এমন ফলাফল পেতে কাজ করবে:
select
a.brand,
c.color,
count(b.id) as countOfBrand
from
brands a
left outer join cars b
on a.ID=b.brand
left outer join colors c
on b.color=c.ID
group by
a.brand,
c.color
+--------+-------+--------------+
| brand | color | countOfBrand |
+--------+-------+--------------+
| BMW | Blue | 1 |
| BMW | White | 1 |
| Ford | Blue | 1 |
| Ford | White | 1 |
| Holden | NULL | 0 |
| Nissan | Black | 1 |
| Smart | White | 1 |
| Toyota | NULL | 1 |
| Toyota | Black | 1 |
| Toyota | Green | 2 |
| Toyota | Red | 1 |
+--------+-------+--------------+
11 rows in set (0.00 sec)
আমরা দেখতে পাচ্ছি, আমাদের দুটি বাইরের প্রশ্নের সাথে যোগদানের আছে এবং প্রত্যাশিত ফলাফলগুলি আসছে।
এখন, কিভাবে যোগদান যারা অন্যান্য ধরনের সম্পর্কে আপনি? ছেদন সম্পর্কে কি?
আচ্ছা, সমস্ত ডেটাবেসগুলি ছেদকে সমর্থন করে না তবে বেশিরভাগ ডেটাবেসে আপনাকে একটি যোগসূত্র (অথবা কমপক্ষে একটি ভাল কাঠামো যেখানে বিবৃতি) মাধ্যমে একটি অন্তর্চ্ছেদ তৈরি করতে দেয়।
একটি অন্তর্চ্ছেদটি উপরে বর্ণিত একটি union
মতো কিছুটা যোগদান করার একটি ধরন - তবে পার্থক্য হল যে এটি শুধুমাত্র সেই সারির সারি প্রদান করে যা একই রকমের (এবং আমি একই রকম) একই সাথে ইউনিয়ন দ্বারা যোগ করা পৃথক পৃথক প্রশ্নগুলির মধ্যে প্রদান করে। শুধুমাত্র প্রতিটি সারিতে অভিন্ন যে সারি ফিরে দেওয়া হবে।
একটি সহজ উদাহরণ যেমন হতে হবে:
select
*
from
colors
where
ID>2
intersect
select
*
from
colors
where
id<4
একটি স্বাভাবিক union
ক্যোয়ারী টেবিলের সমস্ত সারি ( ID>2
এবং অন্য কোনও ID<4
) এর উপরে যেকোনো কিছু ফেরত পাঠাবে, যা একটি সম্পূর্ণ সেটের ফলে, একটি অন্তর্বর্তী প্রশ্ন শুধুমাত্র সারি মিলিং id=3
ফেরত দেবে id=3
হিসাবে এটি উভয় মানদণ্ড পূরণ করে।
এখন, যদি আপনার ডাটাবেস কোনও আন্তঃচুক্তি প্রশ্নের উত্তর দেয় না তবে উপরে দেওয়া প্রশ্নের সাথে সহজেই সংযুক্ত করা যেতে পারে:
select
a.ID,
a.color,
a.paint
from
colors a
join colors b
on a.ID=b.ID
where
a.ID>2
and b.ID<4
+----+-------+----------+
| ID | color | paint |
+----+-------+----------+
| 3 | Blue | Metallic |
+----+-------+----------+
1 row in set (0.00 sec)
যদি আপনি একটি ডাটাবেস ব্যবহার করে দুইটি ভিন্ন টেবিলের মধ্যে একটি ছেদন করতে চান যা অন্তর্নিহিতভাবে একটি ছেদন প্রশ্নের উত্তর দেয় না, তবে আপনাকে টেবিলে প্রতিটি কলামে একটি যোগদান তৈরি করতে হবে।
পার্ট 2 - Subqueries
ঠিক আছে, এখন বস আবার বিস্ফোরিত হয়েছে - আমি ব্র্যান্ডের সাথে আমাদের সমস্ত গাড়িগুলির একটি তালিকা চাই এবং মোট কতগুলি ব্র্যান্ড আমাদের আছে!
এসকিউএল গুডিজ আমাদের ব্যাগ পরবর্তী ট্রিক ব্যবহার করার জন্য এটি একটি দুর্দান্ত সুযোগ। আপনি যদি শব্দটির সাথে অপরিচিত না হন তবে একটি সাবক্রিরি একটি ক্যোয়ারী যা অন্য ক্যোয়ারীর অভ্যন্তরে চলে। তাদের ব্যবহার করার বিভিন্ন উপায় আছে।
আমাদের অনুরোধের জন্য, প্রথমে একটি সহজ ক্যোয়ারী একসাথে রাখুন যা প্রতিটি গাড়ী এবং ব্র্যান্ডকে তালিকাবদ্ধ করবে:
select
a.ID,
b.brand
from
cars a
join brands b
on a.brand=b.ID
এখন, যদি আমরা কেবল ব্র্যান্ড অনুসারে সাজানো গাড়িগুলির গণনা পেতে চাই, তবে অবশ্যই আমরা এটি লিখতে পারি:
select
b.brand,
count(a.ID) as countCars
from
cars a
join brands b
on a.brand=b.ID
group by
b.brand
+--------+-----------+
| brand | countCars |
+--------+-----------+
| BMW | 2 |
| Ford | 2 |
| Nissan | 1 |
| Smart | 1 |
| Toyota | 5 |
+--------+-----------+
সুতরাং, আমরা আমাদের আসল প্রশ্নের সঠিকভাবে গণনা ফাংশন যোগ করতে সক্ষম হওয়া উচিত?
select
a.ID,
b.brand,
count(a.ID) as countCars
from
cars a
join brands b
on a.brand=b.ID
group by
a.ID,
b.brand
+----+--------+-----------+
| ID | brand | countCars |
+----+--------+-----------+
| 1 | Toyota | 1 |
| 2 | Ford | 1 |
| 3 | Nissan | 1 |
| 4 | Smart | 1 |
| 5 | Toyota | 1 |
| 6 | BMW | 1 |
| 7 | Ford | 1 |
| 8 | Toyota | 1 |
| 9 | Toyota | 1 |
| 10 | BMW | 1 |
| 11 | Toyota | 1 |
+----+--------+-----------+
11 rows in set (0.00 sec)
দুঃখজনকভাবে, না, আমরা তা করতে পারি না। কারন আমরা যখন গাড়ী আইডি (কলাম A.ID) যোগ করি তখন আমাদেরকে এটিকে গোষ্ঠীতে যুক্ত করতে হবে - তাই এখন যখন গণনা ফাংশন কাজ করে তখন প্রতি আইডি মিললে শুধুমাত্র একটি আইডি থাকে।
এখানে আমরা একটি subquery ব্যবহার করতে পারেন যেখানে - আসলে আমরা দুটি সম্পূর্ণরূপে বিভিন্ন subquery করতে পারেন যা একই ফলাফল ফিরে যা আমরা এই জন্য প্রয়োজন হবে। প্রথমটি কেবল select
বিভাগে সাবক্যুয়ারিটি স্থাপন করা। এর অর্থ হল আমরা প্রতিটি সময় তথ্য একটি সারি পেতে, subquery চালানো হবে, তথ্য একটি কলাম পেতে এবং তারপর আমাদের সারি মধ্যে এটি পপ।
select
a.ID,
b.brand,
(
select
count(c.ID)
from
cars c
where
a.brand=c.brand
) as countCars
from
cars a
join brands b
on a.brand=b.ID
+----+--------+-----------+
| ID | brand | countCars |
+----+--------+-----------+
| 2 | Ford | 2 |
| 7 | Ford | 2 |
| 1 | Toyota | 5 |
| 5 | Toyota | 5 |
| 8 | Toyota | 5 |
| 9 | Toyota | 5 |
| 11 | Toyota | 5 |
| 3 | Nissan | 1 |
| 4 | Smart | 1 |
| 6 | BMW | 2 |
| 10 | BMW | 2 |
+----+--------+-----------+
11 rows in set (0.00 sec)
এবং বাম !, এই আমাদের করতে হবে। যদিও আপনি লক্ষ্য করেছেন, এই সাব ক্যোয়ারীটি আমরা ফিরে আসা প্রতিটি একক সারির জন্য চালাতে হবে। এমনকি এই সামান্য উদাহরণে, আমাদের কেবল পাঁচটি ভিন্ন ব্র্যান্ডের গাড়ি আছে, তবে উপগ্রহটি 11 বার চলে গেছে কারণ আমাদের কাছে তথ্যগুলির 11 টি সারি রয়েছে যা আমরা ফিরে আসছি। সুতরাং, এই ক্ষেত্রে, এটি কোড লিখতে সবচেয়ে কার্যকর উপায় বলে মনে হচ্ছে না।
একটি ভিন্ন পদ্ধতির জন্য, একটি subquery চালানো এবং এটি একটি টেবিল জাহির করা যাক:
select
a.ID,
b.brand,
d.countCars
from
cars a
join brands b
on a.brand=b.ID
join
(
select
c.brand,
count(c.ID) as countCars
from
cars c
group by
c.brand
) d
on a.brand=d.brand
+----+--------+-----------+
| ID | brand | countCars |
+----+--------+-----------+
| 1 | Toyota | 5 |
| 2 | Ford | 2 |
| 3 | Nissan | 1 |
| 4 | Smart | 1 |
| 5 | Toyota | 5 |
| 6 | BMW | 2 |
| 7 | Ford | 2 |
| 8 | Toyota | 5 |
| 9 | Toyota | 5 |
| 10 | BMW | 2 |
| 11 | Toyota | 5 |
+----+--------+-----------+
11 rows in set (0.00 sec)
ঠিক আছে, তাই আমাদের একই ফলাফল রয়েছে (কিছুটা ভিন্ন আদেশ দেওয়া হয়েছে - মনে হচ্ছে ডাটাবেস প্রথমবার কলামের দ্বারা অর্ডার হওয়া ফলাফলগুলি ফেরত চেয়েছিল) - কিন্তু একই সঠিক সংখ্যা।
সুতরাং, দুটি মধ্যে পার্থক্য কি - এবং আমরা প্রতিটি ধরনের subquery কখন ব্যবহার করা উচিত? প্রথম, আমরা নিশ্চিত যে কিভাবে দ্বিতীয় দ্বিতীয় প্রশ্নের কাজ করে বুঝতে। আমরা আমাদের প্রশ্নের উত্তর from
দুটি টেবিল নির্বাচন করেছি, এবং তারপর একটি প্রশ্ন লিখেছিলাম এবং ডাটাবেসকে বলেছিলাম যে এটি আসলে একটি টেবিল ছিল - যা ডাটাবেসের সাথে পুরোপুরি খুশি। এই পদ্ধতি ব্যবহার করার জন্য কিছু সুবিধা হতে পারে (পাশাপাশি কিছু সীমাবদ্ধতা)। সবচেয়ে গুরুত্বপূর্ণ যে এই subquery একবার দৌড়ে। আমাদের ডাটাবেসের একটি বৃহৎ পরিমাণ তথ্য থাকলে, প্রথম পদ্ধতিতে ব্যাপক উন্নতি হতে পারে। যাইহোক, আমরা একটি টেবিল হিসাবে এটি ব্যবহার করছি, আমাদের কাছে অতিরিক্ত সারি আনা উচিত - যাতে তারা আসলে আমাদের সারির সারিতে যোগদান করতে পারে। আমরা নিশ্চিত যে আমাদের পর্যাপ্ত সারি ডেটা রয়েছে যদি আমরা উপরের প্রশ্নের মত একটি সহজ যোগদান ব্যবহার করতে যাচ্ছি। আপনি যদি মনে করেন, যোগদান শুধুমাত্র ফিরে সারি টানা হবে যে যোগদান উভয় পক্ষের মিলিত তথ্য আছে। আমরা সাবধান না হলে, এই উপসাগরীয়তে মিলিত সারি না থাকলে এটি আমাদের কার টেবিল থেকে বৈধ ডেটা ফিরে আসছে না।
এখন, প্রথম subquery ফিরে তাকান, পাশাপাশি কিছু সীমাবদ্ধতা আছে। কারণ আমরা একটি একক সারিতে ডাটা টেনে আনছি, আমরা কেবলমাত্র ডাটা এক সারি টেনে আনতে পারি। একটি প্রশ্নের প্রশ্নের select
বিভাগে ব্যবহৃত উপসাগরগুলি প্রায়শই কেবল সমষ্টিগত ফাংশন যেমন sum
, count
, max
বা অন্যান্য অনুরূপ সমষ্টিগত ফাংশন ব্যবহার করে। তারা করতে হবে না, কিন্তু প্রায়ই তারা কিভাবে লিখিত হয়।
সুতরাং, আমরা এগিয়ে যেতে আগে, একটি subquery যেখানে আমরা অন্য কোথাও ব্যবহার করতে পারেন দ্রুত দেখুন। আমরা where
ধারাবাহিকভাবে ব্যবহার করতে পারি - এখন, এই উদাহরণটি আমাদের ডাটাবেসের মতো সামান্য সংকোচিত, নিম্নোক্ত ডেটা পাওয়ার আরও ভাল উপায় রয়েছে, তবে এটি কেবল একটি উদাহরণের জন্যই দেখছে, দেখুন:
select
ID,
brand
from
brands
where
brand like '%o%'
+----+--------+
| ID | brand |
+----+--------+
| 1 | Ford |
| 2 | Toyota |
| 6 | Holden |
+----+--------+
3 rows in set (0.00 sec)
এটি আমাদেরকে ব্র্যান্ড আইডি এবং ব্র্যান্ড নামগুলির একটি তালিকা (দ্বিতীয় কলাম শুধুমাত্র আমাদেরকে ব্র্যান্ডগুলি দেখানোর জন্য যুক্ত করা হয়) প্রদান করে যা নামের মধ্যে অক্ষরটি ধারণ করে।
এখন, আমরা এই প্রশ্নের ফলাফলটি যেখানে এই বিভাগে ব্যবহার করতে পারি:
select
a.ID,
b.brand
from
cars a
join brands b
on a.brand=b.ID
where
a.brand in
(
select
ID
from
brands
where
brand like '%o%'
)
+----+--------+
| ID | brand |
+----+--------+
| 2 | Ford |
| 7 | Ford |
| 1 | Toyota |
| 5 | Toyota |
| 8 | Toyota |
| 9 | Toyota |
| 11 | Toyota |
+----+--------+
7 rows in set (0.00 sec)
আপনি দেখতে পারেন, উপধারার তিনটি ব্র্যান্ড আইডি ফেরত পাঠানোর পরেও, আমাদের গাড়ির টেবিলে কেবল দুটিটির জন্য এন্ট্রি ছিল।
এই ক্ষেত্রে, আরও বিস্তারিত জানার জন্য, subquery কাজ করে যেমন আমরা নিম্নলিখিত কোড লিখেছি:
select
a.ID,
b.brand
from
cars a
join brands b
on a.brand=b.ID
where
a.brand in (1,2,6)
+----+--------+
| ID | brand |
+----+--------+
| 1 | Toyota |
| 2 | Ford |
| 5 | Toyota |
| 7 | Ford |
| 8 | Toyota |
| 9 | Toyota |
| 11 | Toyota |
+----+--------+
7 rows in set (0.00 sec)
আবার, আপনি দেখতে পারেন কিভাবে ডেটাবেস থেকে ফিরে আসার সময় ম্যানুয়াল ইনপুট বনাম একটি subquery কিভাবে সারির ক্রম পরিবর্তন করেছে।
আমরা subqueries আলোচনা করা হয়, যখন, একটি subquery সঙ্গে আমরা আর কি করতে পারেন দেখতে দিন:
- আপনি অন্য subquery মধ্যে একটি subquery স্থাপন করতে পারেন, এবং তাই এবং আরও। আপনার ডাটাবেসের উপর নির্ভর করে এমন একটি সীমা রয়েছে, তবে কিছু উন্মাদ এবং ম্যানিয়াকিয়াল প্রোগ্রামারের পুনরাবৃত্তিমূলক ফাংশনগুলির কম, বেশিরভাগ লোকেরা এই সীমাটিকে কখনোই আঘাত করবে না।
- আপনি একটি সংখ্যক সাবquারিতে একক প্রশ্নের মধ্যে, কয়েকটি
select
ধারা, কয়েকটিfrom
অনুচ্ছেদে এবং আরো কয়েকটি ধারাতে কয়েকটি সংখ্যক সাবকুয়ারি স্থাপন করতে পারেনwhere
- শুধু মনে রাখবেন যে আপনি যে প্রত্যেকটিতে ঢোকেন সেটি আপনার প্রশ্নটিকে আরও জটিল করে তুলছে এবং এতে বেশি সময় লাগবে এক্সিকিউট.
যদি আপনার কিছু কার্যকরী কোড লিখতে হয় তবে প্রশ্নটি কয়েকটি উপায়ে লিখতে উপকারী হতে পারে এবং দেখতে পারেন (এটি সময় বা ব্যাখ্যা পরিকল্পনা ব্যবহার করে) যা আপনার ফলাফল পেতে সর্বোত্তম প্রশ্ন। কাজ করে যে প্রথম উপায় সবসময় এটা করার সেরা উপায় হতে পারে না।
ঠিক আছে, আমি এই পোস্টটি খুব মজাদার পেয়েছি এবং আমি একটি প্রশ্ন তৈরি করতে আমার কিছু জ্ঞান ভাগ করতে চাই। এই Fluffeh জন্য ধন্যবাদ। অন্যরা যারা এই পড়তে পারে এবং মনে করতে পারে যে আমি ভুল, তারা আমার উত্তর সম্পাদনা এবং সমালোচনা করতে 101% মুক্ত। ( সত্যি, আমি আমার ভুল সংশোধন করার জন্য অনেক কৃতজ্ঞ। )
আমি MySQL
ট্যাগের প্রায়শই জিজ্ঞাসিত প্রশ্নাবলীর কিছু পোস্ট করব।
ট্রিক নং 1 ( সারির একাধিক অবস্থার সাথে মেলে )
এই স্কিমা দেওয়া
CREATE TABLE MovieList
(
ID INT,
MovieName VARCHAR(25),
CONSTRAINT ml_pk PRIMARY KEY (ID),
CONSTRAINT ml_uq UNIQUE (MovieName)
);
INSERT INTO MovieList VALUES (1, 'American Pie');
INSERT INTO MovieList VALUES (2, 'The Notebook');
INSERT INTO MovieList VALUES (3, 'Discovery Channel: Africa');
INSERT INTO MovieList VALUES (4, 'Mr. Bean');
INSERT INTO MovieList VALUES (5, 'Expendables 2');
CREATE TABLE CategoryList
(
MovieID INT,
CategoryName VARCHAR(25),
CONSTRAINT cl_uq UNIQUE(MovieID, CategoryName),
CONSTRAINT cl_fk FOREIGN KEY (MovieID) REFERENCES MovieList(ID)
);
INSERT INTO CategoryList VALUES (1, 'Comedy');
INSERT INTO CategoryList VALUES (1, 'Romance');
INSERT INTO CategoryList VALUES (2, 'Romance');
INSERT INTO CategoryList VALUES (2, 'Drama');
INSERT INTO CategoryList VALUES (3, 'Documentary');
INSERT INTO CategoryList VALUES (4, 'Comedy');
INSERT INTO CategoryList VALUES (5, 'Comedy');
INSERT INTO CategoryList VALUES (5, 'Action');
প্রশ্ন
কমপক্ষে দুটি Comedy
এবং Romance
বিভাগের সমস্ত চলচ্চিত্র খুঁজুন।
সমাধান
এই প্রশ্ন কখনও কখনও খুব চতুর হতে পারে। মনে হচ্ছে এইরকম একটি প্রশ্ন উত্তর হবে: -
SELECT DISTINCT a.MovieName
FROM MovieList a
INNER JOIN CategoryList b
ON a.ID = b.MovieID
WHERE b.CategoryName = 'Comedy' AND
b.CategoryName = 'Romance'
এসকিউএলফিল্ড ডেমো
এটি কোন ফলাফল উত্পন্ন কারণ স্পষ্টভাবে খুব ভুল। এই ব্যাখ্যাটি প্রতিটি সারিতে শ্রেণীনাম নামমাত্র একটি বৈধ মান রয়েছে। উদাহরণস্বরূপ, প্রথম শর্ত সত্য ফেরত দেয়, দ্বিতীয় শর্তটি সর্বদা মিথ্যা। সুতরাং, AND
অপারেটর ব্যবহার করে, উভয় শর্ত সত্য হতে হবে; অন্যথায়, এটা মিথ্যা হবে। আরেকটি প্রশ্ন এই মত হয়,
SELECT DISTINCT a.MovieName
FROM MovieList a
INNER JOIN CategoryList b
ON a.ID = b.MovieID
WHERE b.CategoryName IN ('Comedy','Romance')
এসকিউএলফিল্ড ডেমো
এবং ফলাফলটি এখনও ভুল কারণ এটি রেকর্ডের সাথে মেলে যা বিভাগের নামতে কমপক্ষে একটি ম্যাচ থাকে। প্রকৃত সমাধানটি মুভির রেকর্ডগুলির সংখ্যা গণনা করে গণনা করা হবে । ইনস্ট্যান্সের সংখ্যাটি শর্তাধীন সরবরাহকৃত মানগুলির মোট নম্বরের সাথে মেলে।
SELECT a.MovieName
FROM MovieList a
INNER JOIN CategoryList b
ON a.ID = b.MovieID
WHERE b.CategoryName IN ('Comedy','Romance')
GROUP BY a.MovieName
HAVING COUNT(*) = 2
এসকিউএলফিল্ড ডেমো (উত্তর)
ট্রিক নং 2 ( প্রতিটি এন্ট্রির জন্য সর্বোচ্চ রেকর্ড )
প্রদত্ত স্কিমা,
CREATE TABLE Software
(
ID INT,
SoftwareName VARCHAR(25),
Descriptions VARCHAR(150),
CONSTRAINT sw_pk PRIMARY KEY (ID),
CONSTRAINT sw_uq UNIQUE (SoftwareName)
);
INSERT INTO Software VALUES (1,'PaintMe','used for photo editing');
INSERT INTO Software VALUES (2,'World Map','contains map of different places of the world');
INSERT INTO Software VALUES (3,'Dictionary','contains description, synonym, antonym of the words');
CREATE TABLE VersionList
(
SoftwareID INT,
VersionNo INT,
DateReleased DATE,
CONSTRAINT sw_uq UNIQUE (SoftwareID, VersionNo),
CONSTRAINT sw_fk FOREIGN KEY (SOftwareID) REFERENCES Software(ID)
);
INSERT INTO VersionList VALUES (3, 2, '2009-12-01');
INSERT INTO VersionList VALUES (3, 1, '2009-11-01');
INSERT INTO VersionList VALUES (3, 3, '2010-01-01');
INSERT INTO VersionList VALUES (2, 2, '2010-12-01');
INSERT INTO VersionList VALUES (2, 1, '2009-12-01');
INSERT INTO VersionList VALUES (1, 3, '2011-12-01');
INSERT INTO VersionList VALUES (1, 2, '2010-12-01');
INSERT INTO VersionList VALUES (1, 1, '2009-12-01');
INSERT INTO VersionList VALUES (1, 4, '2012-12-01');
প্রশ্ন
প্রতিটি সফ্টওয়্যার সর্বশেষ সংস্করণ খুঁজুন। নিম্নোক্ত কলামগুলি প্রদর্শন করুন: SoftwareName
, Descriptions
, LatestVersion
সংস্করণ ( সংস্করণ কোন কলাম থেকে ), DateReleased
সমাধান
কিছু SQL ডেভেলপার ভুলভাবে MAX()
সমষ্টিগত ফাংশন ব্যবহার করে। তারা এই মত তৈরি ঝোঁক,
SELECT a.SoftwareName, a.Descriptions,
MAX(b.VersionNo) AS LatestVersion, b.DateReleased
FROM Software a
INNER JOIN VersionList b
ON a.ID = b.SoftwareID
GROUP BY a.ID
ORDER BY a.ID
এসকিউএলফিল্ড ডেমো
( বেশিরভাগ RDBMS এটির উপর একটি সিনট্যাক্স ত্রুটি তৈরি করে কারণ গোষ্ঠীর অ-একত্রিত কলামগুলি নির্দিষ্ট করে নির্দিষ্ট করে না ) ফলে প্রতিটি সফ্টওয়্যারে সঠিক LatestVersion
তৈরি হয় তবে সম্ভবত DateReleased
। MySQL
Window Functions
এবং Common Table Expression
সমর্থন করে না যদিও কিছু RDBMS ইতিমধ্যেই করে। এই সমস্যাটির subquery
একটি subquery
তৈরি করা যা প্রতিটি সর্বাধিক versionNo
ব্যক্তিগত versionNo
পায় না এবং পরে অন্য টেবিলে যোগদান করা হয়।
SELECT a.SoftwareName, a.Descriptions,
b.LatestVersion, c.DateReleased
FROM Software a
INNER JOIN
(
SELECT SoftwareID, MAX(VersionNO) LatestVersion
FROM VersionList
GROUP BY SoftwareID
) b ON a.ID = b.SoftwareID
INNER JOIN VersionList c
ON c.SoftwareID = b.SoftwareID AND
c.VersionNO = b.LatestVersion
GROUP BY a.ID
ORDER BY a.ID
এসকিউএলফিল্ড ডেমো (উত্তর)
তাই যে এটা ছিল। আমি MySQL
ট্যাগের অন্য কোনও ফ্যাক্টর মনে করিয়ে দিলে শীঘ্রই আরেকটি পোস্ট করব। এই সামান্য নিবন্ধ পড়ার জন্য আপনাকে ধন্যবাদ। আমি আশা করি আপনি অন্তত এই থেকে এমনকি একটু জ্ঞান পেতে।
আপডেট 1
ট্রিক নং 3 ( দুটি আইডিগুলির মধ্যে সর্বশেষ রেকর্ড খোঁজা )
দেওয়া স্কিম
CREATE TABLE userList
(
ID INT,
NAME VARCHAR(20),
CONSTRAINT us_pk PRIMARY KEY (ID),
CONSTRAINT us_uq UNIQUE (NAME)
);
INSERT INTO userList VALUES (1, 'Fluffeh');
INSERT INTO userList VALUES (2, 'John Woo');
INSERT INTO userList VALUES (3, 'hims056');
CREATE TABLE CONVERSATION
(
ID INT,
FROM_ID INT,
TO_ID INT,
MESSAGE VARCHAR(250),
DeliveryDate DATE
);
INSERT INTO CONVERSATION VALUES (1, 1, 2, 'hi john', '2012-01-01');
INSERT INTO CONVERSATION VALUES (2, 2, 1, 'hello fluff', '2012-01-02');
INSERT INTO CONVERSATION VALUES (3, 1, 3, 'hey hims', '2012-01-03');
INSERT INTO CONVERSATION VALUES (4, 1, 3, 'please reply', '2012-01-04');
INSERT INTO CONVERSATION VALUES (5, 3, 1, 'how are you?', '2012-01-05');
INSERT INTO CONVERSATION VALUES (6, 3, 2, 'sample message!', '2012-01-05');
প্রশ্ন
দুই ব্যবহারকারীর মধ্যে সর্বশেষ কথোপকথন খুঁজুন।
সমাধান
SELECT b.Name SenderName,
c.Name RecipientName,
a.Message,
a.DeliveryDate
FROM Conversation a
INNER JOIN userList b
ON a.From_ID = b.ID
INNER JOIN userList c
ON a.To_ID = c.ID
WHERE (LEAST(a.FROM_ID, a.TO_ID), GREATEST(a.FROM_ID, a.TO_ID), DeliveryDate)
IN
(
SELECT LEAST(FROM_ID, TO_ID) minFROM,
GREATEST(FROM_ID, TO_ID) maxTo,
MAX(DeliveryDate) maxDate
FROM Conversation
GROUP BY minFROM, maxTo
)
এসকিউএলফিল্ড ডেমো
আপনি এই জিনিসটি পড়ার সাথে সাথেই এটি টেবিলগুলি খুঁজে বের করে তোলে:
mysql> show columns from colors;
+-------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+----------------+
| id | int(3) | NO | PRI | NULL | auto_increment |
| color | varchar(15) | YES | | NULL | |
| paint | varchar(10) | YES | | NULL | |
+-------+-------------+------+-----+---------+----------------+