سؤال

لدي استعلام SQL يربط جدول التسعير بجدول يحتوي على الإجابات المقدمة من المستخدم.يتم استخدام استعلامي للحصول على السعر بناءً على الكمية المدخلة.فيما يلي بيان SQL الخاص بي:

SELECT JobQuestion.Value, Price.Min, Price.Max, Price.Amount FROM Price
    INNER JOIN JobQuestion 
        ON Price.QuestionFK=JobQuestion.QuestionFK
        AND JobQuestion.JobFK=1
WHERE Price.Min <= JobQuestion.Value 
    AND Price.Max >= JobQuestion.Value

المشكلة هي أن SQL Server يقوم بتشغيل جملة المكان قبل JOIN ويؤدي إلى ظهور الخطأ:

فشل التحويل عند تحويل قيمة varchar إلى نوع البيانات int.

لأنه يقوم بإجراء مقارنات الحد الأدنى والحد الأقصى قبل الانضمام ('TEST' هي قيمة صالحة أدخلها المستخدم في جدول JobQuestion، ولكن لا ينبغي إرجاعها عند ربط JobQuestion بالسعر).أعتقد أن SQL Server يختار تشغيل WHERE لأنه لسبب ما يعتقد المحلل أن ذلك سيكون استعلامًا أكثر كفاءة.إذا قمت فقط بتشغيل

SELECT JobQuestion.Value, Price.Min, Price.Max, Price.Amount FROM Price
    INNER JOIN JobQuestion 
        ON Price.QuestionFK=JobQuestion.QuestionFK
        AND JobQuestion.JobFK=1

أحصل على هذه النتائج مرة أخرى:

500 1       500     272.00
500 501     1000    442.00
500 1001    2000    782.00

لذا، فإن إضافة WHERE يجب أن يقوم بتصفية السجلين الأخيرين وإرجاع السجل الأول فقط.كيف أجبر SQL على تشغيل JOIN أولاً أو استخدام أسلوب آخر لتصفية السجلات التي أحتاجها فقط؟

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

المحلول

أولاً، من المحتمل جدًا أن تكون هذه علامة على سوء التصميم.
إذا لم تتمكن من تغيير المخطط، فربما يمكنك فرض هذا السلوك باستخدام تلميحات.يقتبس:

التلميحات هي خيارات أو إستراتيجيات محددة للتنفيذ بواسطة معالج استعلام SQL Server على عبارات SELECT أو INSERT أو UPDATE أو DELETE.تتجاوز التلميحات أي خطة تنفيذ قد يحددها مُحسِّن الاستعلام للاستعلام.

وبعض أكثر:

حذر:
نظرًا لأن مُحسِّن استعلام SQL Server عادةً ما يحدد أفضل خطة تنفيذ للاستعلام، نوصي باستخدام < join_hint> و < query_hint> و < table_hint> فقط كحل أخير بواسطة المطورين ذوي الخبرة ومسؤولي قواعد البيانات.

نصائح أخرى

وحاول "إعادة صياغة" الاستعلام كما يلي:

SELECT *
FROM   (
          SELECT JobQuestion.Value, 
                 Price.Min, 
                 Price.Max, 
                 Price.Amount 
          FROM   Price
          INNER 
          JOIN   JobQuestion 
                 ON Price.QuestionFK = JobQuestion.QuestionFK
                 AND JobQuestion.JobFK = 1
       ) SQ
WHERE  SQ.Min <= SQ.Value 
AND    SQ.Max >= SQ.Value

وكما في الجواب من مسيحي هايتر، إذا كان لديك خيار، تغيير تصميم الجدول =)

وأنت لا ينبغي مقارنة السلاسل إلى [إينتس]. إذا كان لديك أي تأثير على الإطلاق على تصميم الجدول الخاص بك، ثم تقسيم اثنين من الاستخدامات المختلفة للعمود JobQuestion.Value إلى عمودين مختلفة.

في حال كان لديك أي تأثير على تصميم الجدول الخاص بك - هل يمكنك محاولة لتصفية تلك السجلات مع القيم الرقمية باستخدام <لأ href = "http://msdn.microsoft.com/en-us/library/ms186272٪28SQL 0.90٪ 29.aspx "يختلط =" نوفولو noreferrer "> ISNUMERIC ()؟ اعتقد ان يضيف هذا إلى حسابك حيث شرط يمكن أن تساعد.

ويمكنك على الأرجح إزالة حيث ... وأضيف تلك كما يسند للانضمام لديك. منذ انها صلة داخلية هذا يجب أن تعمل

SELECT JobQuestion.Value, Price.Min, Price.Max, Price.Amount 
FROM Price    
INNER JOIN JobQuestion
ON Price.QuestionFK=JobQuestion.QuestionFK       
AND JobQuestion.JobFK=1
AND Price.Min <= JobQuestion.Value
AND Price.Max >= JobQuestion.Value

ويمكنك استخدام TRY_PARSE خلال تلك الأعمدة السلاسل إلى تحويل إلى رقمية، وإذا SQL لا يمكن تحويل، وسوف تحصل على NULL بدلا من رسالة الخطأ.

وP.S. هذا الشيء هو المرة الأولى التي أدخلت في SQL 2012، لذلك قد يكون مفيدا.

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