এসকিউএল "সাবকিউরিতে নেই যেখানে নির্বাচন করুন" কোনও ফলাফল দেয় না


130

দাবি অস্বীকার: আমি সমস্যাটি বুঝতে পেরেছি (আমি মনে করি), তবে আমি এই সমস্যাটি স্ট্যাক ওভারফ্লোতে যুক্ত করতে চেয়েছিলাম যেহেতু (সহজে) এটি কোথাও খুঁজে পাচ্ছি না। এছাড়াও, কারওর কাছে আমার চেয়ে আরও ভাল উত্তর থাকতে পারে।

আমার একটি ডাটাবেস রয়েছে যেখানে একটি টেবিল "সাধারণ" অন্যান্য কয়েকটি টেবিল দ্বারা রেফারেন্স করা হয়। আমি দেখতে চেয়েছিলাম যে সাধারণ টেবিলের কোন রেকর্ডগুলি অনাথ ছিল (যেমন, অন্যান্য টেবিলগুলির কোনও উল্লেখ নেই) had

আমি এই ক্যোয়ারী চালিয়েছি:

select *
from Common
where common_id not in (select common_id from Table1)
and common_id not in (select common_id from Table2)

আমি জানি যে অনাথ রেকর্ড রয়েছে, কিন্তু কোনও রেকর্ড ফেরত দেওয়া হয়নি। কেন না?

(এটি যদি গুরুত্বপূর্ণ হয় তবে এটি এসকিউএল সার্ভার))


এই স্ট্যাকওভারফ্লো.com/a/129152/1667619 WHW প্রশ্নের উত্তরটি বেশ ভাল উত্তর দেয়।
রুচান

উত্তর:


234

হালনাগাদ:

আমার ব্লগে এই নিবন্ধগুলি আরও বিস্তারিতভাবে পদ্ধতির মধ্যে পার্থক্য বর্ণনা করে:


এই জাতীয় একটি কোয়েরি করার জন্য তিনটি উপায় রয়েছে:

  • LEFT JOIN / IS NULL:

    SELECT  *
    FROM    common
    LEFT JOIN
            table1 t1
    ON      t1.common_id = common.common_id
    WHERE   t1.common_id IS NULL
  • NOT EXISTS:

    SELECT  *
    FROM    common
    WHERE   NOT EXISTS
            (
            SELECT  NULL
            FROM    table1 t1
            WHERE   t1.common_id = common.common_id
            )
  • NOT IN:

    SELECT  *
    FROM    common
    WHERE   common_id NOT IN
            (
            SELECT  common_id
            FROM    table1 t1
            )

যখন table1.common_idঅণনীয় হয় না, এই সমস্ত প্রশ্নগুলি শব্দার্থতভাবে একই।

যখন এটি অলক্ষিত হয় তখন NOT INআলাদা হয়, যেহেতু IN(এবং, অতএব NOT IN) ফিরে আসে NULLযখন একটি যুক্ত একটি তালিকার সাথে কোনও মান মেলে না NULL

এটি বিভ্রান্তিকর হতে পারে তবে আমরা যদি এর বিকল্প বিকল্প বাক্যটি স্মরণ করি তবে আরও স্পষ্ট হয়ে উঠতে পারে:

common_id = ANY
(
SELECT  common_id
FROM    table1 t1
)

এই অবস্থার ফলাফল তালিকার মধ্যে সমস্ত তুলনার একটি বুলিয়ান পণ্য। অবশ্যই, একটি একক NULLমান NULLফলাফল দেয় যা পুরো ফলাফলকেও সরবরাহ করে NULL

আমরা কখনোই স্পষ্টভাবে বলতে পারবে না যে common_idএই তালিকা থেকে কিছু সমান নয়, যেহেতু মূল্যবোধের অন্তত এক NULL

ধরুন আমাদের কাছে এই ডেটা রয়েছে:

common

--
1
3

table1

--
NULL
1
2

LEFT JOIN / IS NULLএবং NOT EXISTSফিরে আসবে 3, NOT INফিরে আসবে কিছুই (যেহেতু এটা সবসময় উভয় মূল্যায়ন করবে FALSEবা NULL)।

ইন MySQL-অ্যালবামযোগ্য কলামে, LEFT JOIN / IS NULLএবং NOT INএর চেয়ে কিছুটা সামান্য (বেশ কয়েকটি শতাংশ) বেশি দক্ষ NOT EXISTS। কলামটি যদি অযোগ্য NOT EXISTSহয় তবে সর্বাধিক দক্ষ (আবার, খুব বেশি নয়)।

ইন Oracle, তিনটি প্রশ্নেরই একই পরিকল্পনা পাওয়া যায় (এ ANTI JOIN)।

ইন SQL Server, NOT IN/ NOT EXISTSআরও দক্ষ, যেহেতু এটির অপ্টিমাইজারটি LEFT JOIN / IS NULLকোনও ANTI JOINদ্বারা অনুকূলিত হতে পারে না ।

ইন PostgreSQL, LEFT JOIN / IS NULLএবং NOT EXISTSঅধিক কার্যকরী হয় NOT IN, সাইন তারা একটি থেকে অপ্টিমাইজ করা হয় Anti Join, যখন NOT INব্যবহারসমূহ hashed subplan(বা এমনকি একটি প্লেইন subplanযদি subquery হ্যাশ করার পক্ষে অত্যন্ত বড় হয়)


8
দুর্দান্ত উত্তর! ধন্যবাদ!
স্টিভেনএমসিডি

এটি দুর্দান্ত এবং খুব সহায়ক
কাভুন

1
+1 কারণ, সাড়ে চার বছর পরে, এই উত্তরটি আমাকে এমন একটি সমস্যা থেকে বেরিয়েছে যে আমাকে স্ট্যাম্প করেছিল!
কারসন 63000

@ কারসন 63000 স্ন্যাপ! এই উত্তরটি দেখার আগে আমি ভেবেছিলাম আমি পাগল হয়ে যাচ্ছি
ববি

1
@ ইসতিয়াকআহমেড: এর NOT EXISTSভিতরে থাকা কোয়েরিটি যদি কোনও সারি দেয় তবে সত্যকে মূল্যায়ন করে। SELECT NULLপাশাপাশি SELECT *বা SELECT 1অন্য কিছু হতে পারে , NOT EXISTSশিকারী সারিগুলির মানগুলি দেখায় না, কেবল তাদের গণনা করে।
কাসনসুই

36

আপনি যদি বিশ্বটি একটি দ্বি-মূল্যবান বুলিয়ান স্থান হতে চান তবে আপনাকে অবশ্যই নাল (তৃতীয় মান) কেসটি আটকাতে হবে।

তালিকার পাশের শূন্যগুলিকে অনুমতি দেয় এমন কলামগুলিতে লিখবেন না। তাদের ফিল্টার আউট!

common_id not in
(
  select common_id from Table1
  where common_id is not null
)

6
ক্লজ-তালিকার শূন্যস্থানগুলি কোয়েরি ফলাফলগুলি হারিয়ে যাওয়ার একটি সাধারণ কারণ।
অ্যামি বি

'নালীর সাথে তুলনা করার সময়, উত্তরটি অজানা "- @ জেরেমি স্টেইনের উত্তর থেকে। থেকে common_id not in, আমরা এখনও যে common_idমান হতে পারে NULL। সুতরাং ফলাফল না পাওয়ার সমস্যাটি কি এখনও টিকে আছে?
ইসতিয়াক আহমেদ

5

টেবিল 1 বা টেবিল 2 এর কমন_আইডের জন্য কিছু নাল মান রয়েছে। পরিবর্তে এই প্রশ্নের ব্যবহার করুন:

select *
from Common
where common_id not in (select common_id from Table1 where common_id is not null)
and common_id not in (select common_id from Table2 where common_id is not null)

1
এক টেবিলের মধ্যে ডাটা থাকলেও অন্যটিতে না থাকলে কী হবে? আপনি কি "এবং" বা "বা" সেখানে চান?
ফিলিপ কেলি

1
আমি কোনও সারণীতে রেফারেন্সহীন রেকর্ডের সন্ধান করছি, তাই আমি AND চাই। আমি প্রশ্নটি পরিষ্কার করব।
জেরেমি স্টেইন

4
select *
from Common c
where not exists (select t1.commonid from table1 t1 where t1.commonid = c.commonid)
and not exists (select t2.commonid from table2 t2 where t2.commonid = c.commonid)

4

শুধু আমার মাথার উপরে বন্ধ...

select c.commonID, t1.commonID, t2.commonID
from Common c
     left outer join Table1 t1 on t1.commonID = c.commonID
     left outer join Table2 t2 on t2.commonID = c.commonID
where t1.commonID is null 
     and t2.commonID is null

আমি কয়েকটি পরীক্ষা চালিয়েছি এবং এখানে আমার ফলাফলগুলি ছিল @ পেটমোরটেকের উত্তর এবং @ রেক্সেমের মন্তব্য।

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

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

যদি উভয়ই কমনআইডিতে সূচকযুক্ত হয়, তবে "বিদ্যমান নেই" ক্যোয়ারী 1/3 সময় চলবে।


1
এটি যেখানে শর্তে একটি AND হওয়া উচিত। অন্যথায়, যে কাজ করে।
জেরেমি স্টেইন

1
আপনার মন্তব্য প্রতি পরিবর্তন। "বা" উভয় টেবিলে এতিমকে তুলে ধরে।
অস্টিন সালোনেন

1
এটা তুলনামূলক ভাল. যাইহোক, আমার সাবকোয়ারির পরিবর্তে বাইরের যোগদানের কোনও কারণ আছে?
জেরেমি স্টেইন

3
পঠনযোগ্যতা প্রাথমিক এক। আমি সন্দেহ করি একটি কার্যকর সম্পাদন পরিকল্পনা উত্পন্ন হবে তবে কোনও ক্যোয়ারী পরিকল্পনা ছাড়াই, আমি নিশ্চিত করতে পারছি না।
অস্টিন সালোনেন

2
এই পদ্ধতিরটি আরও খারাপ যে অস্তিত্ব নেই ব্যবহার করে - এটির পরিবর্তে এটির চেয়ে বেশি সারি আনার ক্ষেত্রে ফলাফল যোগদান করে, তারপরে কলামগুলি শূন্য হওয়ার তুলনায় ফলাফল। এবং নেই অস্তিত্ব বুট করার জন্য আরও পঠনযোগ্য।
ওএমজি পনিস

3
SELECT T.common_id
  FROM Common T
       LEFT JOIN Table1 T1 ON T.common_id = T1.common_id
       LEFT JOIN Table2 T2 ON T.common_id = T2.common_id
 WHERE T1.common_id IS NULL
   AND T2.common_id IS NULL

1
এই পদ্ধতিরটি আরও খারাপ যে অস্তিত্ব নেই ব্যবহার করে - এটির পরিবর্তে এটির চেয়ে বেশি সারি আনার ক্ষেত্রে ফলাফল যোগদান করে, তারপরে কলামগুলি শূন্য হওয়ার তুলনায় ফলাফল। এটি কাজ করে, তবে পারফরম্যান্সটি তেমন ভাল হবে না - সম্ভবত সংযুক্ত সাবকোয়ারিগুলির সাথে IN ব্যবহার করা খারাপ।
ওএমজি পনিস

3

ধরা যাক কমন_আইডের জন্য এই মানগুলি:

Common - 1
Table1 - 2
Table2 - 3, null

আমরা কমন-এ সারিটি ফিরে আসতে চাই, কারণ এটি অন্য কোনও সারণীতে বিদ্যমান নেই। যাইহোক, নাল একটি বানরের রেঞ্চে ছুড়ে ফেলে।

এই মানগুলির সাথে, ক্যোয়ারীটি সমান:

select *
from Common
where 1 not in (2)
and 1 not in (3, null)

এটি সমান:

select *
from Common
where not (1=2)
and not (1=3 or 1=null)

এখান থেকেই সমস্যা শুরু হয়। নাল সাথে তুলনা করার সময়, উত্তরটি অজানা । সুতরাং কোয়েরি হ্রাস

select *
from Common
where not (false)
and not (false or unkown)

মিথ্যা বা অজানা অজানা:

select *
from Common
where true
and not (unknown)

সত্য এবং অজানাও অজানা:

select *
from Common
where unknown

ফলাফলটি অজানা যেখানে শর্তটি রেকর্ড ফিরিয়ে দেয় না, তাই আমরা কোনও রেকর্ড ফিরে পাই না।

এটির সাথে মোকাবিলা করার একটি উপায় হ'ল পরিবর্তে বিদ্যমান অপারেটরটি ব্যবহার করা Ex (একটি সারি হয় বিদ্যমান বা এটি নেই; সারি স্তরের এই নাল অস্পষ্টতার কোনওটিই নয়!)

select *
from Common
where not exists (select common_id from Table1 where common_id = Common.common_id)
and not exists (select common_id from Table2 where common_id = Common.common_id)

2

এটি আমার জন্য কাজ করেছে :)

কমন থেকে * নির্বাচন করুন

কোথায়

কমন_আইড ইন নেই (নির্বাচন করুন ISNULL (কমন_আইডি, 'ডামি-ডেটা') টেবিল 1 থেকে )

এবং সাধারণ_আইডে নেই (টেবিল 2 থেকে আইএসএনএলএল (সাধারণ_আইডি, 'ডামি-ডেটা' নির্বাচন করুন)


@ বিপণনকারী, সাব-কোয়েরিগুলি সর্বদা 1 বা 0 প্রদান করে, মানগুলির তালিকা নয়। তাহলে NOT INসেখানে কীভাবে পারফর্ম করবেন?
ইসতিয়াক আহমেদ


0

আমি যেখানে তাকিয়ে ছিলাম তার একটি উদাহরণ ছিল এবং যেহেতু একটি টেবিলের মূল্য ডাবল হিসাবে রাখে, অন্যটি স্ট্রিং হিসাবে, তারা মিলবে না (বা aালাই ছাড়া মিলবে না)। তবে কেবল নানির্বাচন হিসাবে ... ইন ... কাজ করেছে। অদ্ভুত, তবে ভেবেছিলাম যে অন্য কেউ যদি এই সাধারণ ফিক্সের সম্মুখীন হয় তবে আমি ভাগ করে নেব।


0

উপরের বিষয়টি বুঝতে দয়া করে নীচের উদাহরণটি অনুসরণ করুন:

এছাড়াও অ্যান্টি জয়েন জানতে আপনি নীচের লিঙ্কটি দেখতে পারেন

select department_name,department_id from hr.departments dep
where not exists 
    (select 1 from hr.employees emp
    where emp.department_id=dep.department_id
    )
order by dep.department_name;
DEPARTMENT_NAME DEPARTMENT_ID
Benefits    160
Construction    180
Contracting 190
.......

তবে আমরা NOT INযদি সেই ক্ষেত্রে ব্যবহার করি তবে আমরা কোনও ডেটা পাই না।

select Department_name,department_id from hr.departments dep 
where department_id not in (select department_id from hr.employees );

কোন তথ্য পাওয়া যায় নি

( select department_id from hr.employees) একটি নাল মান ফিরিয়ে দিলে এবং পুরো ক্যোয়ারীটিকে মিথ্যা হিসাবে মূল্যায়ন করা হয় বলে এটি ঘটছে । আমরা যদি নীচের মতো এসকিউএল কিছুটা পরিবর্তন করি এবং এনভিএল ফাংশন দিয়ে নাল মানগুলি পরিচালনা করি তবে আমরা এটি দেখতে পারি।

select Department_name,department_id from hr.departments dep 
where department_id not in (select NVL(department_id,0) from hr.employees )

এখন আমরা ডেটা পাচ্ছি:

DEPARTMENT_NAME DEPARTMENT_ID
Treasury    120
Corporate Tax   130
Control And Credit  140
Shareholder Services    150
Benefits    160
....

NVL ফাংশন সহ নাল মানটি হ্যান্ডেল করার সাথে সাথে আমরা আবার ডেটা পাচ্ছি।


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