এসকিউএল অস্তিত্বের বিবৃতিগুলি কীভাবে কাজ করে?


89

আমি এসকিউএল শিখার চেষ্টা করছি এবং উপস্থিত থাকা সংক্রান্ত বিবৃতিগুলি বোঝার জন্য খুব কঠিন সময় পার করছি। আমি "বিদ্যমান" সম্পর্কে এই উক্তিটি পেরিয়ে এসেছি এবং কিছু বুঝতে পারি না:

বিদ্যমান অপারেটরটি ব্যবহার করে, আপনার সাবকিউরিটি শূন্য, এক, বা অনেকগুলি সারি ফিরতে পারে এবং শর্তটি কেবল subqueryটি কোনও সারি ফিরে পেয়েছিল কিনা তা পরীক্ষা করে। আপনি যদি সাবকোয়ারির নির্বাচিত ধারাটি দেখে থাকেন তবে দেখতে পাবেন এটি একটি একক আক্ষরিক (1) নিয়ে গঠিত; যেহেতু অন্তর্ভুক্ত ক্যোয়ারীর শর্তটি কেবলমাত্র কতগুলি সারি ফিরিয়েছে তা জানতে হবে, উপসর্গটি যে আসল তথ্য দিয়েছিল তা অপ্রাসঙ্গিক।

আমি যা বুঝতে পারি না তা হল বাহ্যিক ক্যোয়ারীটি কীভাবে জানতে পারে যে সাবকিউরিটি কোন সারিতে পরীক্ষা করছে? উদাহরণ স্বরূপ:

SELECT *
  FROM suppliers
 WHERE EXISTS (select *
                 from orders
                where suppliers.supplier_id = orders.supplier_id);

আমি বুঝতে পারি যে সরবরাহকারী থেকে আইডিটি এবং টেবিলটি মেলে, সাবকিউরিটি সত্যটি ফিরে আসবে এবং সরবরাহকারীদের টেবিলের সাথে ম্যাচের সারি থেকে সমস্ত কলাম আউটপুট হবে। আমি যা পাই না তা হল subquery কীভাবে নির্দিষ্ট সারিটি যোগাযোগ করে (সরবরাহকারী আইডি 25 দিয়ে সারিটি বলতে দেয়) প্রিন্ট করা উচিত যদি কেবল সত্য বা মিথ্যা ফেরত আসে।

আমার কাছে মনে হয় বাহ্যিক ক্যোয়ারী এবং সাবকোয়ারির মধ্যে কোনও সম্পর্ক নেই।

উত্তর:


100

এই ভাবে চিন্তা করুন:

থেকে 'প্রতিটি' সারিটির জন্য Suppliers, Orderশর্তটি পূরণ করে এমন সারণীতে একটি সারি রয়েছে কিনা তা পরীক্ষা করুন Suppliers.supplier_id(এটি আউটার ক্যোয়ারী বর্তমান 'সারি' থেকে এসেছে) = Orders.supplier_id। আপনি যখন প্রথম ম্যাচের সারিটি খুঁজে পান, ঠিক সেখানে থামুন - এতে WHERE EXISTSসন্তুষ্ট হয়েছে।

বাহ্যিক ক্যোয়ারী এবং উপসূত্রগুলির মধ্যে ম্যাজিক লিঙ্কটি সত্য যে নিহিত Supplier_idপ্রতিটি সারির জন্য বাহ্যিক ক্যোয়ারী থেকে সাবকোয়রিতে উত্তীর্ণ হয়।

অথবা, এটি অন্য উপায়ে বলতে গেলে, বাইরের ক্যোয়ারীর প্রতিটি টেবিল সারিটির জন্য সাবকোয়ারিটি কার্যকর করা হয়।

এটি সাবউয়েরিটি সম্পূর্ণরূপে নির্বাহ করা হয় এবং 'সত্য / মিথ্যা' পায় এবং তারপরে বাইরের প্রশ্নের সাথে এই 'সত্য / মিথ্যা' শর্তটি মিলানোর চেষ্টা করে।


7
ধন্যবাদ! "এটি সামগ্রিকভাবে চালিত সাবকোরির মতো নয় এবং 'সত্য / মিথ্যা' পায় এবং তারপরে এই 'সত্য / মিথ্যা' শর্তটিকে আউটকোয়ারির সাথে মেলে দেখার চেষ্টা করে" " সত্যই এটি আমার জন্য পরিষ্কার করে দিয়েছে, আমি ভাবতে থাকি যে সাবকিউরিগুলি কীভাবে কাজ করে (এবং তারা বেশিরভাগ সময় কাজ করে) তবে আপনি যা বলেছিলেন তা বোধগম্য কারণ কারণ সাব-বিভাগটি বাইরের ক্যোয়ারির উপর নির্ভর করে এবং তাই প্রতি সারিতে একবার মৃত্যুদন্ড কার্যকর করা উচিত
ক্লারেন্স লিউ

32

আমার কাছে মনে হয় বাহ্যিক ক্যোয়ারী এবং সাবকোয়ারির মধ্যে কোনও সম্পর্ক নেই।

আপনি কী মনে করেন যে অস্তিত্বের উদাহরণের অভ্যন্তরে WHERE ধারাটি কী করছে? যখন সাপ্লাইয়ার্স রেফারেন্সটি বিদ্যমান দফায় FROM বা যোগদানের দফাতে নেই তখন আপনি এই সিদ্ধান্তে কীভাবে পৌঁছবেন?

TRUE / FALSE এর মূল্যবান উপস্থিত রয়েছে এবং মানদণ্ডের প্রথম ম্যাচে TRUE হিসাবে প্রস্থান করে - এই কারণেই এটি এর চেয়ে দ্রুততর হতে পারে IN। এটিও সচেতন থাকুন যে একটি উপস্থিতিতে নির্বাচন করা ধারাটি উপেক্ষা করা হয়েছে - আইই:

SELECT s.*
  FROM SUPPLIERS s
 WHERE EXISTS (SELECT 1/0
                 FROM ORDERS o
                WHERE o.supplier_id = s.supplier_id)

... শূন্য ত্রুটি দ্বারা একটি বিভাগ আঘাত করা উচিত, কিন্তু এটি হবে না। WHERE ধারাটি একটি বিদ্যমান অনুচ্ছেদের সবচেয়ে গুরুত্বপূর্ণ অংশ।

এও জেনে থাকুন যে কোনও জোইন উপস্থিতিগুলির জন্য প্রত্যক্ষ প্রতিস্থাপন নয়, কারণ পিতামাতার সাথে একাধিক সন্তানের রেকর্ড যুক্ত থাকলে সেখানে নকল পিতা-মাতার রেকর্ড থাকবে।


4
আমি এখনও কিছু মিস করছি। যদি এটি প্রথম ম্যাচে প্রস্থান করে তবে আউটপুটটি কীভাবে সমস্ত ফলাফল হয়ে যাবে যেখানে o.supplierid = s.supplierid? পরিবর্তে এটি কি কেবল প্রথম ফলাফলটি আউটপুট করে না?
ড্যান

4
@ ড্যান: EXISTSপ্রস্থানগুলি, প্রথম ম্যাচে সত্য ফিরে - কারণ সরবরাহকারী কমপক্ষে একবার অর্ডার সারণীতে উপস্থিত হয়। অর্ডারে একাধিক শিশুর সম্পর্ক থাকার কারণে যদি আপনি সরবরাহকারীর ডেটারের নকল দেখতে চান, তবে আপনাকে একটি যোগদান করতে হবে। তবে বেশিরভাগই সেই অনুলিপিটি চান না এবং ক্যোয়ারিতে ওভারহেড যুক্ত করার জন্য GROUP / DISTINCT দ্বারা চালানো দায়বদ্ধ। এসকিউএল সার্ভারের EXISTSচেয়ে বেশি দক্ষ SELECT DISTINCT ... FROM SUPPLIERS JOIN ORDERS ..., ইদানীং ওরাকল বা মাইএসকিউএলে পরীক্ষা করা হয়নি।
ওএমজি পনিস

আমার একটি প্রশ্ন ছিল, বাইরের ক্যোয়ারিতে নির্বাচিত প্রতিটি রেকর্ডের জন্য কি মিল রয়েছে? সরবরাহকারীদের থেকে 5 টি সারি নির্বাচিত হলে আমরা 5 বার অর্ডার থেকে আনতে পারি।
রাহুল কদুকার 15

24

হয় আপনি ব্যবহার অভিন্ন ফলাফল তৈরী করতে পারে JOIN, EXISTS, IN, অথবা INTERSECT:

SELECT s.supplier_id
FROM suppliers s
INNER JOIN (SELECT DISTINCT o.supplier_id FROM orders o) o
    ON o.supplier_id = s.supplier_id

SELECT s.supplier_id
FROM suppliers s
WHERE EXISTS (SELECT * FROM orders o WHERE o.supplier_id = s.supplier_id)

SELECT s.supplier_id 
FROM suppliers s 
WHERE s.supplier_id IN (SELECT o.supplier_id FROM orders o)

SELECT s.supplier_id
FROM suppliers s
INTERSECT
SELECT o.supplier_id
FROM orders o

4
মহান উত্তর, কিন্তু মনে রাখবেন যে এটা ভাল ব্যবহার পারস্পরিক সম্পর্ক এড়াতে বিদ্যমান না করা হয়
ফ্লোরিয়ান Fröhlich

4
আপনার কাছে কি জিজ্ঞাসাটি মনে হয় যদি সরবরাহকারীদের 10M সারি থাকে এবং অর্ডারগুলিতে 100M সারি থাকে এবং কেন?
তেজা

7

আপনার যদি এমন কোনও ধারা থাকে যা দেখতে এরকম দেখায়:

WHERE id in (25,26,27) -- and so on

আপনি সহজেই বুঝতে পারবেন যে কিছু সারি কেন ফিরে এসেছে এবং কিছুগুলি কেন নয়।

যখন ক্লজটি এর মত হয়:

WHERE EXISTS (select * from orders where suppliers.supplier_id = orders.supplier_id);

এটির অর্থ কেবল: একই আইডির সাথে অর্ডার সারণিতে বিদ্যমান রেকর্ড রয়েছে এমন সারিগুলি ফিরিয়ে দিন।


2

এটি একটি খুব ভাল প্রশ্ন, তাই আমি এই বিষয়টি নিয়ে আমার ব্লগে একটি খুব বিস্তারিত নিবন্ধ লেখার সিদ্ধান্ত নিয়েছি ।

ডাটাবেস টেবিল মডেল

আসুন ধরে নেওয়া যাক আমাদের আমাদের ডাটাবেসে নিম্নলিখিত দুটি সারণী রয়েছে যা একের মধ্যে একাধিক টেবিলের সম্পর্ক তৈরি করে।

এসকিউএল বিদ্যমান সারণী

studentটেবিল পিতা বা মাতা, এবংstudent_grade শিশু টেবিল যেহেতু এটি একটি student_id পররাষ্ট্র কী কলাম ছাত্র টেবিলে আইডি প্রাথমিক কী কলাম উল্লেখ হয়েছে।

student tableনিম্নলিখিত দুটি রেকর্ড রয়েছে:

| id | first_name | last_name | admission_score |
|----|------------|-----------|-----------------|
| 1  | Alice      | Smith     | 8.95            |
| 2  | Bob        | Johnson   | 8.75            |

এবং, student_gradeটেবিলটি শিক্ষার্থীদের প্রাপ্ত গ্রেডগুলি সংরক্ষণ করে:

| id | class_name | grade | student_id |
|----|------------|-------|------------|
| 1  | Math       | 10    | 1          |
| 2  | Math       | 9.5   | 1          |
| 3  | Math       | 9.75  | 1          |
| 4  | Science    | 9.5   | 1          |
| 5  | Science    | 9     | 1          |
| 6  | Science    | 9.25  | 1          |
| 7  | Math       | 8.5   | 2          |
| 8  | Math       | 9.5   | 2          |
| 9  | Math       | 9     | 2          |
| 10 | Science    | 10    | 2          |
| 11 | Science    | 9.4   | 2          |

এসকিউএল উপস্থিত রয়েছে

ধরা যাক আমরা ম্যাথ ক্লাসে 10 গ্রেড প্রাপ্ত সকল শিক্ষার্থী পেতে চাই।

আমরা যদি কেবল শিক্ষার্থী শনাক্তকরণে আগ্রহী, তবে আমরা এই জাতীয় একটি কোয়েরি চালাতে পারি:

SELECT
    student_grade.student_id
FROM
    student_grade
WHERE
    student_grade.grade = 10 AND
    student_grade.class_name = 'Math'
ORDER BY
    student_grade.student_id

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

studentগণিতে একটি 10 ​​গ্রেড রয়েছে এমন রেকর্ডগুলি ফিল্টার করার জন্য , আমরা এইগুলির মতো বিদ্যমান এসকিউএল অপারেটরটি ব্যবহার করতে পারি:

SELECT
    id, first_name, last_name
FROM
    student
WHERE EXISTS (
    SELECT 1
    FROM
        student_grade
    WHERE
        student_grade.student_id = student.id AND
        student_grade.grade = 10 AND
        student_grade.class_name = 'Math'
)
ORDER BY id

উপরের ক্যোয়ারীটি চালানোর সময়, আমরা দেখতে পাচ্ছি যে কেবলমাত্র অ্যালিস সারিটি নির্বাচিত হয়েছে:

| id | first_name | last_name |
|----|------------|-----------|
| 1  | Alice      | Smith     |

বাহ্যিক ক্যোয়ারী studentআমাদের ক্লায়েন্টটিতে ফিরে আসতে আগ্রহী সারি কলামগুলি নির্বাচন করে । যাইহোক, WHERE ধারাটি একটি সম্পর্কিত অভ্যন্তরীণ subquery সহ উপস্থিতি অপারেটরটি ব্যবহার করছে।

সাবকিউরিটি অন্তত একটি রেকর্ড প্রত্যাবর্তন করে এবং কোনও সারি নির্বাচন না করা হলে মিথ্যাটি উপস্থিত থাকলে উপস্থিতি অপারেটর সত্য বলে প্রত্যাবর্তন করে। ডাটাবেস ইঞ্জিনটিকে সাবকোরিটি পুরোপুরি চালাতে হবে না। যদি একটি একক রেকর্ডটি মিলে যায় তবে উপস্থিতি অপারেটরটি সত্য ফিরে আসে এবং সম্পর্কিত অন্যান্য ক্যোয়ারী সারিটি নির্বাচিত হয়।

অভ্যন্তরীণ সাবকোয়ারিটি পারস্পরিক সম্পর্কযুক্ত কারণ student_gradeটেবিলের ছাত্র_আইডি কলামটি বাইরের ছাত্র সারণির আইডি কলামের সাথে মিলেছে।


কি দুর্দান্ত উত্তর। আমি মনে করি আমি ধারণাটি পাইনি কারণ আমি একটি ভুল উদাহরণ ব্যবহার করছিলাম। EXISTকেবল কি সম্পর্কযুক্ত subquery সঙ্গে কাজ করে? আমি প্রায় 1 টি টেবিলযুক্ত কোয়েরি নিয়ে প্রায় খেলছিলাম SELECT id FROM student WHERE EXISTS (SELECT 1 FROM student WHERE student.id > 1)। আমি জানি আমি কী লিখেছি তা একটি সাধারণ WHEE ক্যোয়ারী দ্বারা অর্জন করা যেতে পারে তবে আমি এটি উপস্থিতি বুঝতে এটি ব্যবহার করছিলাম। আমি সব সারি পেয়েছি। এটি কি সত্যিকারের কারণে যে আমি সম্পর্কযুক্ত সাবকোয়ারি ব্যবহার করিনি? ধন্যবাদ
বোভেন লিউ

আপনি কেবল বহির্মুখী ক্যোয়ারের রেকর্ডগুলি ফিল্টার করতে চাইলে এটি কেবল সম্পর্কিত সম্পর্কের জন্যই বোঝায় for আপনার ক্ষেত্রে অভ্যন্তরীণ কোয়েরিটি যেখানে সত্য
ভ্লাদ মিহালসিয়া

ধন্যবাদ ভ্লাদ আমি যা ভেবেছিলাম. এটি কেবল একটি অদ্ভুত ধারণা যা ঘটেছিল যখন আমি এটির সাথে ঘোরাঘুরি করছিলাম। আমি আন্তরিকতার সাথে সংযুক্ত subquery ধারণা জানি না। এবং এখন অভ্যন্তরীণ ক্যোয়ারির সাথে বাইরের ক্যোয়ারীর সারিগুলি ফিল্টার করার জন্য এটি আরও অনেক বেশি অর্থবোধ করে।
বোভেন লিউ

0

অস্তিত্বের অর্থ subquery কমপক্ষে একটি সারি ফেরত, সত্যিই এটি। সেক্ষেত্রে এটি একটি সম্পর্কযুক্ত সাবকোয়ারি কারণ এটি বাইরের টেবিলের সরবরাহকারী_আইডিটি অভ্যন্তরীণ সারণীর সরবরাহকারী_আইডিতে পরীক্ষা করে। এই ক্যোয়ারী কার্যকরভাবে বলে:

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

এই ক্ষেত্রে আপনি একই কাজ করতে পারেন অনার যোগ দিয়ে।

SELECT suppliers.* 
  FROM suppliers 
 INNER 
  JOIN orders 
    ON suppliers.supplier_id = orders.supplier_id;

পোনির মন্তব্যটি সঠিক। আপনাকে এই যোগদানের সাথে গ্রুপিং করতে হবে বা আপনার প্রয়োজনীয় ডেটার উপর নির্ভর করে আলাদা নির্বাচন করতে হবে।


4
একাধিক শিশুর রেকর্ড কোনও পিতামাতার সাথে যুক্ত থাকলে অভ্যন্তরীণ যোগদানটি উপস্থিতি থেকে আলাদা ফলাফল আনবে - সেগুলি অভিন্ন নয়।
ওএমজি পনিস

আমি মনে করি আমার বিভ্রান্তিটি হতে পারে যে আমি পড়েছি যে একটি অস্তিত্বের সহিত সাবকুরিটি সত্য বা মিথ্যা প্রত্যাবর্তন করে; তবে এটি কেবল ফিরে আসে না যে এটি ফিরে আসে, তাই না? সাবকিউরিও কি সমস্ত "সরবরাহকারীদের অর্ডার টেবিলে একই সারি থাকা" সরবরাহ করছে? তবে যদি তা হয় তবে কীভাবে EXISTS বিবৃতিটি বুলিয়ান ফলাফল প্রদান করবে? আমি পাঠ্য বইয়ে যা পড়ছি তা বলছে যে এটি কেবল একটি বুলিয়ান ফলাফল দেয়, তাই কোডের ফলাফলটি পুনরায় ফিরে আসার সাথে মিলিয়ে নিতে আমার খুব কষ্ট হচ্ছে।
ড্যান

ফাংশনের মতো অস্তিত্ব পড়ুন ... উপস্থিতি (ফলাফল সেট)। রেজাল্টসেটের সারি থাকলে অস্তিত্ব ফাংশনটি সত্য হয়ে যায়, যদি এটি খালি থাকে। মূলত এটি।
ডেভিড ফেলস

4
@ ড্যান, বিবেচনা করুন যে প্রতিটি উত্স সারির জন্য অস্তিত্ব () যুক্তিযুক্তভাবে স্বতন্ত্রভাবে মূল্যায়ন করা হয় - এটি সম্পূর্ণ প্রশ্নের জন্য একক মান নয়।
আরভো

-1

আপনি যা বর্ণনা করেন তা হ'ল একটি সম্পর্কিত সম্পর্কযুক্ত সাব- কোয়েরির সাথে তথাকথিত ক্যোয়ারী ।

(সাধারণভাবে) এটি এমন কিছু যা এর পরিবর্তে একটি যোগ ব্যবহার করে কোয়েরিটি লিখে আপনার এড়াতে চেষ্টা করা উচিত:

SELECT suppliers.* 
FROM suppliers 
JOIN orders USING supplier_id
GROUP BY suppliers.supplier_id

কারণ অন্যথায়, subquery বাইরের ক্যোয়ারী প্রতিটি সারির জন্য কার্যকর করা হবে।


4
এই দুটি সমাধান সমতুল্য নয়। ordersএতে যোগ দেওয়ার শর্তের সাথে একাধিক সারি থাকলে একের বেশি উপস্থিত থাকলে জয়েন্টগুলি উপস্থিতি সাবকিউয়ের চেয়ে আলাদা ফলাফল দেয় ।
a_horse_with_no_name

4
বিকল্প সমাধানের জন্য ধন্যবাদ। তবে আপনি কি পরামর্শ দিচ্ছেন যে যদি পারস্পরিক সম্পর্কযুক্ত সাবকোয়্যারির সাথে একটি বিকল্প দেওয়া হয় এবং যোগদান করতে চান তবে আমি যোগদানের সাথে যেতে হবে কারণ এটি আরও দক্ষ?
সানি_দেব
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.