سؤال

لقد تعلمت للتو (أمس) استخدام "موجود" بدلاً من "في".

 BAD
 select * from table where nameid in ( 
          select nameid from othertable where otherdesc =  'SomeDesc' )      
 GOOD
 select * from table t where exists ( 
          select nameid from othertable o where t.nameid = o.nameid and otherdesc =  'SomeDesc' )      

ولدي بعض الأسئلة حول هذا:

1) الشرح كما فهمت هو: "السبب في أن هذا أفضل هو أنه سيتم إرجاع القيم المطابقة فقط بدلاً من إنشاء قائمة ضخمة من النتائج المحتملة".هل هذا يعني أنه على الرغم من أن الاستعلام الفرعي الأول قد يُرجع 900 نتيجة، فإن الاستعلام الفرعي الثاني سيُرجع 1 فقط (نعم أو لا)؟

2) في الماضي تلقيت شكوى من RDBMS:"يمكن استرداد أول 1000 صف فقط"، هل هذا النهج الثاني سيحل هذه المشكلة؟

3) ما هو نطاق الاسم المستعار في الاستعلام الفرعي الثاني؟...هل الاسم المستعار موجود فقط بين قوسين؟

على سبيل المثال

 select * from table t where exists ( 
          select nameid from othertable o where t.nameid = o.nameid and otherdesc =  'SomeDesc' )      
 AND 
          select nameid from othertable o where t.nameid = o.nameid and otherdesc =  'SomeOtherDesc' )      

بمعنى، إذا استخدمت نفس الاسم المستعار (o for tableothertable) في "موجود" الثاني، فهل سيمثل أي مشكلة مع الأول موجود؟أم أنهم مستقلون تماما؟

هل هذا شيء يتعلق بـ Oracle فقط أم أنه صالح لمعظم RDBMS؟

شكرًا جزيلاً

هل كانت مفيدة؟

المحلول

إنه خاص بكل نظام إدارة قواعد بيانات (DBMS) ويعتمد على مُحسِّن الاستعلام.يكتشف بعض المحسنين جملة IN ويترجمونها.

في جميع أنظمة إدارة قواعد البيانات (DBMS) التي قمت باختبارها، يكون الاسم المستعار صالحًا فقط داخل ( )

راجع للشغل، يمكنك إعادة كتابة الاستعلام على النحو التالي:

select t.* 
from table t 
join othertable o on t.nameid = o.nameid 
    and o.otherdesc in ('SomeDesc','SomeOtherDesc');

و للإجابة على أسئلتك:

  1. نعم
  2. نعم
  3. نعم

نصائح أخرى

وأنت تمشي داخل الأراضي معقدة، المعروفة باسم '-الاستفسارات الفرعية المترابطة. وبما أننا لم يكن لديك معلومات مفصلة حول الجداول والهياكل الأساسية، بعض الإجابات يمكن أن يكون إلا "ربما".

في الأولي الخاص بك في الاستعلام، وتدوين سيكون ساري المفعول أم لا OtherTable يحتوي على NameID العمود (و، في الواقع، سواء OtherDesc كما هو معمول به عمود في الجدول أو OtherTable - وهي ليست واضحة في أي من الأمثلة، ولكن من المفترض هو عمود من OtherTable). هذا السلوك هو ما يجعل ارتباطا شبه الاستعلام إلى الاستعلام الفرعية المترابطة. بل هو أيضا مصدر الروتيني لهموم الناس عند تشغيلها لأول مرة في ذلك - دائما عن طريق الصدفة. منذ ولايات مستوى SQL سلوك تفسير اسم في الاستعلام الفرعي أنها تشير إلى عمود في الاستعلام الخارجي إذا لم يكن هناك عمود مع اسم ذات الصلة في الجداول المذكورة في الاستعلام الفرعي ولكن هناك عمود مع اسم ذات الصلة في الجداول المشار إليها في الاستعلام (الرئيسي) الخارجي، أي منتج الذي يريد أن يدعي المطابقة لل(هذا قليلا من) فإن معيار SQL تفعل شيئا مختلفا.

والإجابة على Q1 الخاص بك هو "الامر يتوقف"، ولكن نظرا افتراضات منطقية (NameID كما هو معمول به عمود في كل من الجداول؛ OtherDesc موجود فقط في OtherTable)، يجب أن تكون النتائج هي نفسها من حيث مجموعة البيانات التي تم إرجاعها، ولكن قد لا يكون معادلا من حيث الأداء.

والإجابة على Q2 الخاص بك هو أنه في الماضي، كنت تستخدم أقل شأنا إذا DBMS يست معيبة. إذا كان دعم موجودا، ثم DBMS قد لا يزال يشكو من أصل لنتيجة.

والجواب على Q3 الخاص بك كما ينطبق على أول وجود الاستعلام "تي متاح كاسم مستعار في جميع أنحاء بيان، ولكن يا متاح فقط كاسم مستعار داخل الأقواس". كما ينطبق على المثال الثاني المربع الخاص بك - مع وربط اثنين من يختار الفرعية (ثاني الذي يفتقد قوس فتح عندما أنا أبحث في ذلك)، ثم "تي متاح كاسم مستعار في جميع أنحاء بيان ويشير إلى نفسه الجدول، ولكن هناك نوعان من الأسماء المستعارة المختلفة سواء المسمى 'س'، واحدة لكل الاستعلام الفرعي ". لاحظ أن الاستعلام قد ترجع أية بيانات إذا OtherDesc هي فريدة من نوعها لقيمة NameID الواردة في OtherTable. خلاف ذلك، فإنه يتطلب صفين في OtherTable مع نفسه NameID والقيمتين OtherDesc لكل صف في الجدول مع تلك القيمة NameID.

  1. خاص بأوراكل:عندما تكتب استعلامًا باستخدام جملة IN، فإنك تخبر المُحسِّن المستند إلى القواعد أنك تريد أن يقوم الاستعلام الداخلي بتوجيه الاستعلام الخارجي.عندما تكتب "موجود" في عبارة "حيث"، فإنك تخبر المُحسِّن أنك تريد تشغيل الاستعلام الخارجي أولاً، باستخدام كل قيمة لجلب قيمة من الاستعلام الداخلي.يرى "الفرق بين IN وEXISTS في الاستعلامات الفرعية".
  2. من المحتمل.
  3. الاسم المستعار المعلن داخل الاستعلام الفرعي يعيش داخل الاستعلام الفرعي.بالمناسبة، لا أعتقد أن المثال الخاص بك مع الاستعلامات الفرعية 2 ANDed هو SQL صالح.هل تقصد UNION بدلاً من AND؟

وأنا شخصيا أود أن استخدام الانضمام، بدلا من فرعي لذلك.

SELECT t.*
FROM yourTable t
    INNER JOIN otherTable ot
        ON (t.nameid = ot.nameid AND ot.otherdesc = 'SomeDesc')

ومن الصعب التعميم موجود دائما خير من IN. منطقيا إذا كان هذا هو الحال، ثم المجتمع SQL قد استبدلت في مع المشرقية ... أيضا، يرجى ملاحظة أن في والمشرقية ليست نفسه، قد تكون النتائج مختلفة عند استخدام اثنين ...

ومع IN، عادة في جدول مسح كامل من الجدول الداخلية مرة واحدة دون إزالة القيم الخالية (حتى إذا كان لديك بالقيم الفارغة في الجدول الداخلية الخاصة بك، سوف IN تقم بإزالة بالقيم الخالية افتراضيا) ... وبينما توجد يزيل فارغة وفي حالة المترابطة فرعي، فإنه يعمل الاستعلام الداخلي للكل صف من الاستعلام الخارجي.

وعلى افتراض عدم وجود بلا قيم وفي استعلام بسيط (مع عدم وجود ارتباط)، EXIST قد تؤدي بشكل أفضل إذا كان الصف كنت تجد ليس في الصف الأخير. إذا كان يحدث أن تكون في الصف الأخير، يوجد قد تحتاج إلى تفحص حتى نهاية مثل IN .. أداء مماثلا لذلك ...

ولكن في والمشرقية ليست قابلة للتبديل ...

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top