এসকিউএল কোয়েরি একাধিক সারণী থেকে ডেটা ফেরত দেয়


434

আমি নিম্নলিখিত জানতে চাই:

  • কীভাবে আমার ডাটাবেসে একাধিক টেবিল থেকে ডেটা পাবেন?
  • কোন ধরণের পদ্ধতি এটি করার আছে?
  • কীভাবে যোগ দেয় এবং ইউনিয়ন হয় এবং কীভাবে তারা একে অপরের থেকে আলাদা?
  • আমি কখন অন্যের তুলনায় প্রতিটি ব্যবহার করব?

আমি এটি আমার (উদাহরণস্বরূপ - পিএইচপি) অ্যাপ্লিকেশনটিতে ব্যবহারের পরিকল্পনা করছি, তবে ডাটাবেসের বিরুদ্ধে একাধিক প্রশ্ন চালাতে চাই না, একক কোয়েরিতে একাধিক টেবিল থেকে আমার কাছে কী বিকল্প থাকতে হবে?

দ্রষ্টব্য: আমি এটি লিখছি কারণ আমি পিএইচপি সারিতে ক্রমাগত যে অসংখ্য প্রশ্ন আসি সে সম্পর্কে একটি ভাল লিখিত গাইডের সাথে লিঙ্ক করতে সক্ষম হতে চাই, তাই আমি উত্তর পোস্ট করার সময় আমি আরও বিশদে এটির সাথে লিঙ্ক করতে পারি।

উত্তরগুলি নিম্নলিখিতটি কভার করে:

  1. পর্ব 1 - যোগদান এবং ইউনিয়নসমূহ
  2. পার্ট 2 - উপশক্তি
  3. পার্ট 3 - কৌশল এবং দক্ষ কোড
  4. পার্ট 4 - দা ক্লোজ থেকে সাবকিউরিজ
  5. পর্ব 5 - জন ট্রিক্সের মিশ্র ব্যাগ

উত্তর:


469

পর্ব 1 - যোগদান এবং ইউনিয়নসমূহ

এই উত্তরটি কভার করে:

  1. অংশ 1
  2. অংশ ২
    • সাবকিউরিগুলি - সেগুলি কী, তারা কোথায় ব্যবহার করা যায় এবং কী কী সন্ধান করা উচিত
    • কার্তেসিয়ান একেতে যোগ দিলেন - ওঃ দুর্ভাগ্য!

একটি ডাটাবেসে একাধিক সারণী থেকে ডেটা পুনরুদ্ধার করার বিভিন্ন উপায় রয়েছে। এই উত্তরে, আমি এএনএসআই -92 সংযুক্ত সিনট্যাক্স ব্যবহার করব। এটি বেশ কয়েকটি অন্যান্য টিউটোরিয়ালের চেয়ে আলাদা হতে পারে যা পুরানো এএনএসআই -৯৯ সিনট্যাক্স ব্যবহার করে (এবং আপনি যদি 89 এর সাথে ব্যবহার করেন তবে এটি খুব কম স্বজ্ঞাত মনে হতে পারে - তবে আমি যা বলতে পারি তা চেষ্টা করেই করা যায়) কারণ এটি অনেক সহজ যখন প্রশ্নগুলি আরও জটিল হতে শুরু করে তখন বুঝতে। কেন এটি ব্যবহার করবেন? একটি কর্মক্ষমতা লাভ আছে? সংক্ষিপ্ত উত্তর নেই, কিন্তু এটি হল একবার আপনি এটি ব্যবহার করতে পারেন অথবা পড়ার জন্য সহজ। এই সিনট্যাক্সটি ব্যবহার করে অন্যান্য লোকদের দ্বারা লিখিত প্রশ্নগুলি পড়া আরও সহজ।

আমি একটি ছোট caryard ধারণা ব্যবহার করতে যাচ্ছি যা কোন গাড়ী উপলব্ধ তা ট্র্যাক রাখতে একটি ডাটাবেস আছে। মালিক আপনাকে তার আইটি কম্পিউটার লোক হিসাবে ভাড়া করেছে এবং প্রত্যাশা করে যে আপনি হ্যাট পড়ার সময় যে ডেটা জিজ্ঞাসা করেছেন তা তাকে ফেলে দিতে সক্ষম হবেন।

আমি অনেকগুলি সন্ধানের টেবিল তৈরি করেছি যা চূড়ান্ত সারণী দ্বারা ব্যবহৃত হবে। এটি আমাদের থেকে কাজ করার জন্য একটি যুক্তিসঙ্গত মডেল দেবে। শুরু করার জন্য, আমি নীচের কাঠামোগত উদাহরণস্বরূপ ডাটাবেসের বিরুদ্ধে আমার প্রশ্নগুলি চালাচ্ছি। আমি শুরু করার সময় ঘটে যাওয়া সাধারণ ভুলগুলি সম্পর্কে চিন্তা করার চেষ্টা করব এবং তাদের সাথে কী কী ঘটে যায় তা ব্যাখ্যা করব - পাশাপাশি অবশ্যই সেগুলি কীভাবে সংশোধন করতে হবে তাও দেখিয়ে দেব।

প্রথম টেবিলটি কেবল একটি রঙের তালিকা যাতে আমরা জানতে পারি যে গাড়ীর উঠোনটিতে আমাদের কী রঙ রয়েছে।

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)

ব্র্যান্ডস টেবিলটি বিভিন্ন ব্র্যান্ডের গাড়ি বাইরে বেরিয়ে সম্ভবত ক্যারিয়ার বিক্রি করতে পারে identif

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)

এটি আমাদের বিভিন্ন ধরণের যোগদানের নীচের উদাহরণগুলি কভার করতে পর্যাপ্ত ডেটা (আশা করি) দেবে এবং এগুলি সার্থক করার জন্য পর্যাপ্ত ডেটা দেবে।

সুতরাং এর কৌতুক intoুকতে গিয়ে, বস তার কাছে থাকা সমস্ত স্পোর্ট কারের আইডি জানতে চায় ।

এটি একটি সহজ দুটি টেবিল যোগদান। আমাদের কাছে একটি টেবিল রয়েছে যা এতে উপলব্ধ স্টক সহ মডেল এবং টেবিলটি সনাক্ত করে। আপনি দেখতে পাচ্ছেন, টেবিলের modelকলামের ডেটা আমাদের থাকা carsটেবিলের modelsকলামের সাথে সম্পর্কিত cars। এখন, আমরা জানি যে মডেল টেবিলের 1জন্য একটি আইডি রয়েছে 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আমাদের বিবৃতিতে থাকা ধারাটি আমাদের মূল টেবিলের সাথে লিঙ্ক করেছে (আমি প্রায়শই কোনও সারণী ব্যবহার করি যা অনুসন্ধান বা মাত্রা সারণির চেয়ে তথ্য থাকে The কোয়েরিটি কেবল পাশাপাশি কাজ করবে সমস্ত টেবিলে সরিয়ে দেওয়া, তবে কখনই কম জ্ঞান হবে আমরা কয়েক মাসের মধ্যে এটি পড়ার জন্য এই ক্যোয়ারিতে ফিরে আসি, সুতরাং প্রায়শই একটি কোয়েরিটি লেখার চেষ্টা করা ভাল যা সহজ এবং সহজেই বুঝতে পারে - এটি স্বজ্ঞাতভাবে লিখে রাখুন, সুন্দর ইনডেন্টিং ব্যবহার করুন যাতে সবকিছু যেমন পরিষ্কার হয় তেমন হয় এটি হতে পারে you আপনি যদি অন্যকে শেখাতে যান তবে তাদের বৈশিষ্ট্যগুলিতে এই বৈশিষ্ট্যগুলি প্রবর্তনের চেষ্টা করুন - বিশেষত যদি আপনি তাদের সমস্যা সমাধান করছেন।

এই পদ্ধতিতে আরও বেশি করে সারণীর সংযোগ স্থাপন করা সম্পূর্ণভাবে সম্ভব।

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যা মাঠের brandsটেবিলের সাথে ফিরে যুক্ত হয়েছিল ID, এটি এটি হিসাবে এটি করা যেতে পারে:

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)

ভাল godশ্বর, এটা কুশ্রী। তবে, যতদূর ডাটাবেস সম্পর্কিত, ঠিক এটিই যা চাওয়া হয়েছিল। ক্যোয়ারী, আমরা জন্য জিজ্ঞাসা IDথেকে carsএবং modelথেকে models। যাইহোক, কারণ আমরা তা নির্দিষ্ট করেন নি কিভাবে টেবিল যোগদানের জন্য, ডাটাবেজ মিলেছে করেনি যে প্রথম টেবিল থেকে সারি সঙ্গে যে দ্বিতীয় টেবিল থেকে সারি।

ঠিক আছে, সুতরাং বস ফিরে আসেন, এবং তিনি আরও তথ্য চান। আমি একই তালিকাটি চাই, তবে এটিতে 4 ডাব্লুডিও অন্তর্ভুক্ত করব

তবে এটি আমাদের এটি সম্পাদন করার জন্য দুটি ভিন্ন উপায়ের দিকে তাকানোর দুর্দান্ত অজুহাত দেয়। আমরা যেখানে এখানে আর একটি শর্ত যুক্ত করতে পারলাম এর মতো:

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ক্যোয়ারী কাজ করবে তা দেখানোর জন্য এটি দুর্দান্ত বাহানা use

আমরা জানি যে নিম্নলিখিতগুলি সমস্ত স্পোর্টস গাড়ি ফেরত দেবে:

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

এবং নিম্নলিখিতগুলি সমস্ত 4WD ফিরে আসবে:

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তাদের মধ্যে একটি ধারা যুক্ত করে, দ্বিতীয় ক্যোয়ারির ফলাফলগুলি প্রথম ক্যোয়ারীর ফলাফলগুলিতে সংযুক্ত হবে।

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ত্রুটির কারণ হতে পারে - যতদূর ফলাফল সম্পর্কিত, কলামটি IDপরিবর্তে বলা হয় a.ID- যদিও একই উফর উভয় প্রশ্নের ক্ষেত্রে ব্যবহৃত হয়েছে।
  • আমাদের কেবল একটি order byবিবৃতি থাকতে পারে এবং এটি অবশ্যই শেষ বিবৃতি হিসাবে হওয়া উচিত।

পরবর্তী উদাহরণগুলির জন্য, আমি আমাদের টেবিলগুলিতে কয়েকটি অতিরিক্ত সারি যুক্ত করছি।

আমি Holdenব্র্যান্ডের টেবিলে যুক্ত করেছি। আমিও যোগ করেছেন মধ্যে একটি সারি carsযে হয়েছে colorএর মান 12- যা রং টেবিলের কোন সংশয়ের অবকাশ নেই।

ঠিক আছে, বস আবার অনুরোধ করে বার বার অনুরোধ করে বললেন - * আমরা যে ব্র্যান্ডটি বহন করি তার একটি গণনা এবং এতে থাকা গাড়িগুলির সংখ্যা আমি চাই! `- সাধারণভাবে, আমরা কেবল আমাদের আলোচনার একটি আকর্ষণীয় অংশে পৌঁছে যাই এবং বস আরও কাজ চায় ।

রাইটিও, সুতরাং প্রথম জিনিসটি আমাদের করা দরকার সম্ভাব্য ব্র্যান্ডগুলির একটি সম্পূর্ণ তালিকা পাওয়া।

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প্রকারের হতে পারে । বাম বা ডান নির্ধারণ করে যে কোন টেবিলটি সম্পূর্ণ অন্তর্ভুক্ত রয়েছে is এ left outer joinবামে থাকা টেবিল থেকে সমস্ত সারি অন্তর্ভুক্ত করবে, যখন (আপনি এটি অনুমান করেছিলেন) একটি right outer joinটেবিল থেকে সমস্ত ফলাফলকে ডানে আনবে into

কিছু ডাটাবেস এমন একটিকে অনুমতি দেবে 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)

যেমনটি আমরা দেখতে পাচ্ছি, ক্যোয়ারিতে আমাদের দুটি বহিরাগত যোগদান রয়েছে এবং প্রত্যাশা অনুযায়ী ফলাফলগুলি আসবে।

এখন, আপনি জিজ্ঞাসা করা অন্যান্য ধরণের সম্পর্কে কীভাবে? মোড় সম্পর্কে কি?

ভাল, সমস্ত ডাটাবেস সমর্থন করে না intersectionতবে বেশিরভাগ সমস্ত ডাটাবেস আপনাকে একটি যোগদানের মাধ্যমে ছেদ তৈরি করতে দেয় (বা একটি সুগঠিত যেখানে কমপক্ষে বিবৃতি দেয়)।

একটি ছেদটি unionউপরের বর্ণিত হিসাবে কিছুটা মিলের এক প্রকারের সংযোগ - তবে পার্থক্যটি হ'ল এটি ইউনিয়নে যোগদানকারী পৃথক পৃথক প্রশ্নের মধ্যে কেবলমাত্র সারি (এবং আমি অর্থ অভিন্ন) বলে সারি করে data প্রতিটি ক্ষেত্রে সাদৃশ্যযুক্ত সারিগুলিই ফিরে আসবে।

একটি সাধারণ উদাহরণ যেমন হবে:

select
    *
from
    colors
where
    ID>2
intersect
select
    *
from
    colors
where
    id<4

যখন কোনও সাধারণ unionক্যোয়ারী সারণীর সমস্ত সারি ফিরে আসে (প্রথম কোয়েরিতে কোনও কিছু ফেরত দেওয়া ID>2এবং দ্বিতীয়টি যে কোনও কিছু রয়েছে ID<4) এর ফলে পুরো সেট আসবে, তবে একটি ছেদকৃত ক্যোয়ারী কেবল id=3উভয় মানদণ্ডের সাথে মিল রেখেই সারি মিলবে ।

এখন, যদি আপনার ডাটাবেসটি কোনও intersectক্যোয়ারিকে সমর্থন করে না , তবে উপরেরটি নীচের কোয়েরির সাথে খুব সহজেই সমন্বিত হতে পারে:

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
টুইটগুলি আমার একটি পরামর্শ আছে: আপনি যদি এটিকে একটি হত্যাকারী এসকিউএল টিউটোরিয়াল বানাতে চান তবে আপনি কেবল ভেন চিত্রটি যুক্ত করতে পারেন না; আমি ডান এখনই বামে বুঝতে পেরেছি এবং ডান তাদের ধন্যবাদ জানায়। ব্যক্তিগত অনুরোধ: আপনার সাধারণ ভুল / পারফরম্যান্স টিউনিং সম্পর্কিত কোনও টিউটোরিয়াল রয়েছে?
StrayChild01

25
আহারে. আমার স্ক্রোল হুইলটি ভেঙে গেছে। দুর্দান্ত প্রশ্নোত্তর। আমি আশা করি আমি এই 10 বার upvote করতে পারে।
অমল মুরালি

3
হেই, ইতিবাচক মতামতের জন্য ধন্যবাদ। যদিও স্ক্রোলিং চালিয়ে যান, এটি কেবল প্রথম উত্তর ছিল। এসও বলেছিলেন যে আমার উত্তরটি এটি একটি "উত্তর" হিসাবে ফিট করার জন্য অনেক দীর্ঘ ছিল তাই আমাকে কয়েকটি ব্যবহার করতে হয়েছিল :)
ফ্লাফ

7
সত্যিই, আমি মনে করি এই উত্তরটি কিছুটা ছোট করা দরকার।
einpoklum

দুর্দান্ত নিবন্ধ। ডাটাবেজ এ যোগদান করেছে 101.
maqs

101

ঠিক আছে, আমি এই পোস্টটি খুব আকর্ষণীয় পেয়েছি এবং আমি কোয়েরি তৈরির বিষয়ে আমার কিছু জ্ঞান ভাগ করতে চাই। এই জন্য ধন্যবাদ 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'

এসকিউএলফিডাল ডেমো

এটি অবশ্যই খুব ভুল কারণ এটি কোনও ফল দেয় না । এর বাখ্যা শুধুমাত্র এক বৈধ মান আছে যে CategoryNameউপর প্রতিটি সারির । উদাহরণস্বরূপ, প্রথম শর্তটি সত্য হয় , দ্বিতীয় শর্তটি সর্বদা মিথ্যা। সুতরাং, ANDঅপারেটর ব্যবহার করে , উভয় শর্ত সত্য হওয়া উচিত; অন্যথায়, এটি মিথ্যা হবে। আর একটি ক্যোয়ারী এরকম,

SELECT  DISTINCT a.MovieName
FROM    MovieList a
        INNER JOIN CategoryList b
            ON a.ID = b.MovieID
WHERE   b.CategoryName IN ('Comedy','Romance')

এসকিউএলফিডাল ডেমো

এবং ফলাফলটি এখনও ভুল কারণ এটি রেকর্ড করতে মেলে যাতে কমপক্ষে একটি ম্যাচ রয়েছে categoryNameপ্রকৃত সমাধান সিনেমা প্রতি রেকর্ড দৃষ্টান্ত সংখ্যা বেড়ে চলেছে দ্বারা হবে । শর্তে সরবরাহ করা মানগুলির মোট সংখ্যার সাথে উদাহরণের সংখ্যাটি মিলবে।

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( VersionNo কলাম থেকে ),DateReleased

সমাধান

কিছু এসকিউএল বিকাশকারী ভুল করে 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 কারণ নন-সমষ্টিগত কলামের কিছু উল্লেখ না এই একটি বাক্য গঠন ত্রুটি উত্পন্ন group byদফা ফলাফলের সঠিক উত্পাদন করে) LatestVersionপ্রতিটি সফ্টওয়্যার কিন্তু স্পষ্টত DateReleasedভুল। MySQLসমর্থন করে না Window Functionsএবং Common Table Expressionএখনও কিছু আরডিবিএমএস ইতিমধ্যে করেছে। এই সমস্যার উপর ভিত্তি করে তৈরি করা হ'ল এমন একটি তৈরি করা subqueryযা versionNoপ্রতিটি সফ্টওয়্যারটিতে স্বতন্ত্র সর্বাধিক পায় এবং পরে অন্যান্য টেবিলে যোগ দেওয়া হয় joined

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
)

এসকিউএলফিডাল ডেমো


অসাধারণ! একজন সাবধান জন, আপনার প্রথম সমাধানটি কেবলমাত্র দুটি ক্ষেত্রের ক্ষেত্রে অনন্য বাধা থাকার কারণে কাজ করে। আপনি একটি সাধারণ সমস্যা সমাধানে আরও সাধারণ সমাধান ব্যবহার করতে পারেন। আমার মতে একমাত্র সমাধান হ'ল পৃথক নির্বাচনের জন্য comedyএবং এর জন্য romanceHavingস্বল্পতা মামলা তারপর ..
nawfal

@ নওফাল আসলেই নয়, যদি অনন্য বাধা যুক্ত না করা হয় তবে আপনাকে অবশ্যই এসকিউএলফিডাল ডেমো যুক্তdistinct ধারাটি যুক্ত করতে হবে : ডি
জন উ

63

পার্ট 2 - উপশক্তি

ঠিক আছে, এখন বস আবার ফেটে গেছে - আমি ব্র্যান্ড সহ আমাদের সমস্ত গাড়ির তালিকা এবং আমাদের কতটি ব্র্যান্ড রয়েছে তার মোট তালিকা চাই!

সাবকিউরি - এসকিউএল গুডি আমাদের ব্যাগের পরবর্তী কৌশলটি ব্যবহার করার এটি দুর্দান্ত সুযোগ। আপনি যদি এই শব্দটির সাথে অপরিচিত হন তবে একটি সাবকোয়ারি এমন একটি কোয়েরি যা অন্য কোয়েরির ভিতরে চলে runs এগুলি ব্যবহার করার বিভিন্ন উপায় রয়েছে।

আমাদের অনুরোধের জন্য প্রথমে একসাথে একটি সাধারণ ক্যোয়ারী রাখি যা প্রতিটি গাড়ি এবং ব্র্যান্ডের তালিকা তৈরি করবে:

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)

দুঃখের বিষয়, না, আমরা এটি করতে পারি না। কারণটি হ'ল আমরা যখন গাড়ীর আইডি (কলাম এ.আইডি) যুক্ত করি তখন আমাদের এটিকে গ্রুপে যুক্ত করতে হয় - সুতরাং এখন, যখন গণনা ফাংশনটি কাজ করে, তখন প্রতি আইডিতে একটি আইডি মিলে যায়।

এটি আমরা যেখানে সাব-কোয়েরিটি ব্যবহার করতে পারি - বাস্তবে আমরা দুটি সম্পূর্ণ ভিন্ন ধরণের সাবকোরি করতে পারি যা আমাদের জন্য প্রয়োজনীয় ফলাফল একই রকম করে দেবে। প্রথম কেবলমাত্র subquery করা হয় selectদফা। এর অর্থ প্রতিবার যখনই আমরা একটি সারির ডেটা পাই, সাবকিউরিটি বন্ধ হয়ে যাবে, একটি কলামের ডেটা পেয়েছে এবং তারপরে এটি আমাদের তথ্য সারিটিতে পপ করে।

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)

এবং বাম! এটি আমাদের করবে। আপনি যদি খেয়াল করে থাকেন তবে এই সাব কোয়েরিতে আমরা ফিরে আসা প্রতিটি একক সারির ডেটা চালাতে হবে। এমনকি এই সামান্য উদাহরণেও, আমাদের কাছে কেবল পাঁচটি ভিন্ন ব্র্যান্ডের গাড়ি রয়েছে, তবে সাবকেইটি এগারবার বার চলেছিল কারণ আমাদের কাছে এগারো সারি ডেটা রয়েছে যা আমরা ফিরে আসছি। সুতরাং, এই ক্ষেত্রে, কোডটি লেখার পক্ষে সবচেয়ে কার্যকর উপায় বলে মনে হয় না।

ভিন্ন পদ্ধতির জন্য, একটি সাবকিউারি চালাতে দিন এবং এটি টেবিলে ভান করুন:

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)

ঠিক আছে, সুতরাং আমাদের একই ফলাফল রয়েছে (কিছুটা আলাদাভাবে অর্ডার করা হয়েছে - এটি মনে হয় যে এই সময়কৃত প্রথম কলামের দ্বারা অর্ডার করা ফলাফলগুলি ডাটাবেসগুলি ফিরিয়ে দিতে চেয়েছিল) - তবে একই সঠিক সংখ্যাগুলি।

সুতরাং, দুজনের মধ্যে পার্থক্য কী - এবং আমাদের প্রতিটি প্রকারের সাবকিউরিটি কখন ব্যবহার করা উচিত? প্রথমে নিশ্চিত হয়ে যাক যে আমরা বুঝতে পারি যে দ্বিতীয় ক্যোয়ারী কীভাবে কাজ করে। আমরা fromআমাদের ক্যোয়ারির ধারাটিতে দুটি সারণী নির্বাচন করেছি এবং তারপরে একটি ক্যোয়ারী লিখে ডাটাবেসকে জানিয়েছি যে এটি আসলে একটি টেবিল ছিল - যা ডাটাবেসটি পুরোপুরি খুশি। সেখানে পারবেন এই পদ্ধতি ব্যবহার করে কিছু সুবিধা (সেইসাথে কিছু সীমাবদ্ধতা) হতে। সর্বাগ্রে এই যে এই সাবকোয়ারিটি একবার চালানো হয়েছিল । যদি আমাদের ডাটাবেসে প্রচুর পরিমাণে ডেটা থাকে, তবে প্রথম পদ্ধতির তুলনায় সেখানে ব্যাপক উন্নতি হতে পারে। তবে, আমরা এটি একটি টেবিল হিসাবে ব্যবহার করছি, আমাদের অতিরিক্ত সারি ডেটা আনতে হবে - যাতে তারা আসলে আমাদের সারি ডেটাতে যোগ দিতে পারে। আমাদেরও নিশ্চিত হতে হবে যে পর্যাপ্ত পরিমাণ রয়েছেউপরের ক্যোয়ারির মতো আমরা যদি কোনও সাধারণ যোগ যোগ করতে যাচ্ছি তবে সারিগুলির ডেটা। আপনি যদি প্রত্যাহার করে থাকেন তবে যোগদানটি কেবল সারিগুলিকেই টেনে তুলবে যাতে জোড়ার উভয় দিকে মিল রয়েছে । আমরা যদি সাবধান না হয়ে থাকি তবে এই সাবকোয়রিতে কোনও মিলের সারি না থাকলে আমাদের গাড়ির টেবিল থেকে বৈধ ডেটা ফেরত না দেওয়া হতে পারে।

এখন, প্রথম সাবকিউয়ের দিকে ফিরে তাকানো, কিছু সীমাবদ্ধতাও রয়েছে। যেহেতু আমরা তথ্যগুলিকে একক সারিতে ফিরিয়ে আনছি , আমরা কেবলমাত্র এক সারি ডেটা পিছনে টানতে পারি । ব্যবহৃত Subqueries selectএকটি ধারা ক্যোয়ারী খুব প্রায়ই যেমন শুধুমাত্র একটি সমষ্টিগত ফাংশন ব্যবহার sum, count, maxবা অন্য অনুরূপ সমষ্টিগত ফাংশন। তারা না আছে , কিন্তু যে কিভাবে তারা লিখিত হয়।

সুতরাং, আমরা এগিয়ে যাওয়ার আগে, আরও কীভাবে আমরা সাবকিউরি ব্যবহার করতে পারি সেদিকে একবার নজর দেওয়া যাক। আমরা এটিকে 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)

এটি আমাদের ব্র্যান্ডের আইডি এবং ব্র্যান্ডের নামের (দ্বিতীয় কলামটি কেবল আমাদের ব্র্যান্ডগুলি দেখানোর জন্য যুক্ত করা হয়েছে) oএর নামের সাথে চিঠিটি ফিরিয়ে দেয় that

এখন, আমরা এই ক্যোয়ারির ফলাফলগুলিকে এমন একটি ক্লাজে ব্যবহার করতে পারি:

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)

আপনি দেখতে পাচ্ছেন, যদিও সাবকিউরিটি তিনটি ব্র্যান্ডের আইডি ফিরিয়ে দিচ্ছিল, আমাদের গাড়ির টেবিলের মধ্যে কেবল দুটির জন্য প্রবেশিকা রয়েছে।

এই ক্ষেত্রে, আরও বিশদের জন্য সাবকোয়ারিটি কাজ করছে যেন আমরা নীচের কোডটি লিখেছি:

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 মধ্যে একটি subquery স্থাপন করতে পারেন, এবং আরও অনেক কিছু। আপনার ডাটাবেসের উপর নির্ভর করে এমন একটি সীমা রয়েছে, তবে কিছু উন্মাদ এবং ম্যানিয়াকাল প্রোগ্রামারটির পুনরাবৃত্তি ফাংশনগুলির সংক্ষিপ্ততা, বেশিরভাগ লোকেরা কখনই এই সীমাটিকে আঘাত করতে পারে না।
  • আপনি কয়েক একটি একক ক্যোয়ারী মধ্যে subqueries একটি নম্বর স্থাপন করতে পারেন, selectদফা, কিছু fromধারা এবং আরও দম্পতি whereদফা - শুধু মনে রাখবেন যে প্রতিটি এক আপনি রাখা আপনার প্রশ্নের আরো জটিল উপার্জন করা হয় এবং সম্ভবত দীর্ঘ নিতে এক্সিকিউট.

আপনার যদি কিছু দক্ষ কোড লেখার প্রয়োজন হয়, তবে কোয়েরিটি বেশ কয়েকটি উপায়ে লেখার পক্ষে এবং আপনার ফলাফলগুলি পাওয়ার জন্য সর্বোত্তম ক্যোয়ারী (এটি সময় নির্ধারণের মাধ্যমে বা একটি ব্যাখ্যা পরিকল্পনা ব্যবহার করে) উপকারী হতে পারে। প্রথম উপায় যে কাজ করে তা সর্বদা এটি করার সর্বোত্তম উপায় নাও হতে পারে।


নতুন ডেভসের জন্য অত্যন্ত গুরুত্বপূর্ণ: আপনি যদি সাব- কোয়েরিকে যোগ হিসাবে (উপরে দেখানো) হিসাবে ব্যবহার না করতে পারেন তবে সাবকুইরিগুলি সম্ভবত প্রতিটি ফলাফলের জন্য একবার চালিত হয় ।
শিওনক্রস

59

পার্ট 3 - কৌশল এবং দক্ষ কোড

() দক্ষতায় মাইএসকিউএল

আমি ভেবেছিলাম যে টিপস এবং কৌশলগুলি সামনে এসেছে এর জন্য আমি কিছু অতিরিক্ত বিট যুক্ত করব।

একটি প্রশ্ন আমি দেখতে পাচ্ছি যে, আমি দুটি টেবিলের সাথে কীভাবে মিলে না যাওয়া সারিগুলি পাই এবং আমি উত্তরটি নীচের মতো কিছু হিসাবে স্বীকৃত দেখি (আমাদের গাড়ি এবং ব্র্যান্ডের সারণির উপর ভিত্তি করে - যা হোল্ডেনকে তালিকাভুক্ত করেছে ব্র্যান্ড, তবে গাড়ির টেবিলে উপস্থিত হবে না):

select
    a.ID,
    a.brand
from
    brands a
where
    a.ID not in(select brand from cars)

এবং হ্যাঁ এটি কাজ করবে।

+----+--------+
| ID | brand  |
+----+--------+
|  6 | Holden |
+----+--------+
1 row in set (0.00 sec)

তবে এটি কিছু ডাটাবেসে দক্ষ নয় । এটি সম্পর্কে জিজ্ঞাসা করে স্ট্যাক ওভারফ্লো প্রশ্নটির একটি লিঙ্ক , এবং আপনি যদি নিতম্বের কৌতুক পেতে চান তবে এখানে গভীরতার নিবন্ধে একটি দুর্দান্ত

সংক্ষিপ্ত উত্তরটি হল, যদি অপটিমাইজার দক্ষতার সাথে এটি পরিচালনা করে না, তবে মিল না পাওয়া সারিগুলি পাওয়ার জন্য নীচের মতো একটি কোয়েরি ব্যবহার করা আরও ভাল:

select
    a.brand
from
    brands a
        left join cars b
            on a.id=b.brand
where
    b.brand is null

+--------+
| brand  |
+--------+
| Holden |
+--------+
1 row in set (0.00 sec)

সাবকোরিতে একই টেবিল সহ টেবিল আপডেট করুন

আহ্, অন্য প্রবীণ তবে গুডি - পুরাতন আপনি এফআরওএম ক্লজে আপডেটের জন্য টার্গেট টেবিল 'ব্র্যান্ড' নির্দিষ্ট করতে পারবেন না

মাইএসকিউএল আপনাকে update...একই টেবিলের সাব-সাবলেট সহ একটি কোয়েরি চালানোর অনুমতি দেবে না । এখন, আপনি ভাবতে পারেন, কেন কেবল এটিকে ঘৃণা করবেন না যেখানে ডানদিকে? তবে আপনি যদি max()অন্য সারির একগুচ্ছ তারিখের সাথে কেবল সারিটি আপডেট করতে চান ? আপনি ঠিক যেখানে এটি করতে পারবেন না যেখানে একটি ধারা।

update 
    brands 
set 
    brand='Holden' 
where 
    id=
        (select 
            id 
        from 
            brands 
        where 
            id=6);
ERROR 1093 (HY000): You can't specify target table 'brands' 
for update in FROM clause

তো, আমরা কি এহ করতে পারি না? ঠিক আছে, ঠিক না। এমন একটি ছদ্মবেশী কাজ রয়েছে যা অবাক করে দেওয়ার মতো বিশাল সংখ্যক ব্যবহারকারী জানেন না - যদিও এর মধ্যে এমন কিছু হ্যাকারি অন্তর্ভুক্ত রয়েছে যা আপনাকে মনোযোগ দিতে হবে।

আপনি subquery অন্য subquery মধ্যে আটকে রাখতে পারেন, যা দুটি প্রশ্নের মধ্যে একটি ফাঁক যথেষ্ট রাখে যাতে এটি কাজ করবে। তবে নোট করুন যে কোনও লেনদেনের মধ্যে ক্যোয়ারিকে আটকে রাখা সবচেয়ে নিরাপদ হতে পারে - এটি কোয়েরি চলাকালীন টেবিলে করা অন্য কোনও পরিবর্তনকে আটকাবে prevent

update 
    brands 
set 
    brand='Holden' 
where id=
    (select 
        id 
    from 
        (select 
            id 
        from 
            brands 
        where 
            id=6
        ) 
    as updateTable);

Query OK, 0 rows affected (0.02 sec)
Rows matched: 1  Changed: 0  Warnings: 0

3
কেবলমাত্র এটি লক্ষ করতে চাই যে যেখানে নেই (নির্মাণের অস্তিত্ব রয়েছে) 'দক্ষতার দৃষ্টিকোণ' থেকে অনেকটা অভিন্ন তবে আমার মতে পড়া / বোঝা আরও সহজ। তারপরে আবার, আমার জ্ঞান এমএসএসকিউএলে সীমাবদ্ধ এবং অন্য প্ল্যাটফর্মগুলিতে যদি একই হয় তবে আমি মানত করতে পারি না।
21

আমি অন্য দিন মাত্র এই ধরণের তুলনার চেষ্টা করেছি, যেখানে নট IN () এর প্রায় কয়েক শ আইডির একটি তালিকা ছিল এবং এটির সাথে কোয়েরির যোগদানের সংস্করণটির মধ্যে কোনও পার্থক্য নেই। আপনি হাজার বা বিলিয়নে উঠলে সম্ভবত এটি একটি পার্থক্য করে।
বাটল বাটকাস

18

আপনি এফআরএম কীওয়ার্ডে একাধিক প্রশ্নের ধারণা ব্যবহার করতে পারেন। আমি আপনাকে একটি উদাহরণ দেখাতে দিন:

SELECT DISTINCT e.id,e.name,d.name,lap.lappy LAPTOP_MAKE,c_loc.cnty COUNTY    
FROM  (
          SELECT c.id cnty,l.name
          FROM   county c, location l
          WHERE  c.id=l.county_id AND l.end_Date IS NOT NULL
      ) c_loc, emp e 
      INNER JOIN dept d ON e.deptno =d.id
      LEFT JOIN 
      ( 
         SELECT l.id lappy, c.name cmpy
         FROM   laptop l, company c
         WHERE l.make = c.name
      ) lap ON e.cmpy_id=lap.cmpy

আপনি চান যতগুলি টেবিল ব্যবহার করতে পারেন। বাইরের যোগদান এবং ইউনিয়নটি যেখানে প্রয়োজন তা ব্যবহার করুন এমনকি এমনকি টেবিলের সাবকোয়্যারির মধ্যেও।

টেবিল এবং ক্ষেত্র হিসাবে অনেকগুলি জড়িত করার এটি একটি খুব সহজ পদ্ধতি।


8

আপনি যে জিনিসটি পড়ছেন সেগুলি আশা করে এটি সারণীগুলি সন্ধান করে:

jsfiddle

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    |                |
+-------+-------------+------+-----+---------+----------------+
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.