كيف أجبر SQL Server 2005 على تشغيل صلة قبل أين؟
-
10-07-2019 - |
سؤال
لدي استعلام 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، لذلك قد يكون مفيدا.