Как мне заставить SQL Server 2005 выполнить соединение перед where?

StackOverflow https://stackoverflow.com/questions/1644092

Вопрос

У меня есть 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 запускает предложение where перед СОЕДИНЕНИЕМ, и оно выдает ошибку:

Сбой преобразования при преобразовании значения переменной 'TEST' varchar в тип данных int.

потому что он выполняет сравнения min и max перед объединением ('TEST' - это допустимое значение, введенное пользователем в таблице JobQuestion, но не должно быть возвращено при соединении JobQuestion с Price).Я полагаю, что 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 сначала запустить СОЕДИНЕНИЕ или использовать другой метод, чтобы отфильтровать только те записи, которые мне нужны?

Это было полезно?

Решение

Во-первых, это очень вероятный признак плохого дизайна.
Если вы не можете изменить схему, возможно, вы могли бы принудительно применить это поведение, используя подсказки . Цитата:

  

Подсказки - это параметры или стратегии, указанные для применения процессором запросов SQL Server в инструкциях SELECT, INSERT, UPDATE или DELETE. Подсказки переопределяют любой план выполнения, который оптимизатор запросов может выбрать для запроса.

И еще немного:

  

Внимание:
  Поскольку оптимизатор запросов SQL Server обычно выбирает лучший план выполнения для запроса, мы рекомендуем & Lt; join_hint > ;, < query_hint > и < table_hint GT &; использовать в качестве крайней меры опытные разработчики и администраторы баз данных.

Другие советы

Попробуйте " перефразируйте " запрос выглядит следующим образом:

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 на два различных столбца.

Если вы не имеете никакого влияния на дизайн таблицы - не могли бы вы отфильтровать эти записи с помощью числовых значений, используя ISNUMERIC ()? Я думаю, что добавление этого к вашему предложению where может помочь.

Скорее всего, вы можете удалить where ... и просто добавить их в качестве предикатов в ваше объединение. Так как это внутреннее соединение, это должно работать

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 для преобразования столбцов strings в числовые, и если SQL не сможет преобразовать, он выдаст вам NULL вместо сообщения об ошибке.

P.S.Эта вещь впервые представлена в SQL 2012, так что может быть полезной.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top