Как заставить SQL Server 2005 запускать соединение перед тем, где? - PullRequest
2 голосов
/ 29 октября 2009

У меня есть 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 перед JOIN и выдает ошибку:

Преобразование не удалось при преобразовании значение varchar 'TEST' для типа данных 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 запустить сначала JOIN или использовать другую технику для фильтрации только нужных мне записей?

Ответы [ 6 ]

4 голосов
/ 29 октября 2009

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

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

Согласно ответу Кристиана Хейтера, если у вас есть выбор, измените дизайн таблицы =)

2 голосов
/ 29 октября 2009

Вы не должны сравнивать строки с целыми числами. Если вы имеете какое-либо влияние на дизайн таблицы, то разбейте два различных использования столбца JobQuestion.Value на два различных столбца.

1 голос
/ 29 октября 2009

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

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

И еще:

Внимание:
Поскольку оптимизатор запросов SQL Server обычно выбирает лучший план выполнения для запроса, мы рекомендуем, чтобы , и

0 голосов
/ 22 января 2013

Вы можете использовать TRY_PARSE для столбцов этой строки, чтобы преобразовать в числовые значения, и если SQL не может преобразовать, вместо сообщения об ошибке вы получите NULL.

P.S. Это впервые введено в SQL 2012, поэтому может быть полезно.

0 голосов
/ 29 октября 2009

Скорее всего, вы можете удалить 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
0 голосов
/ 29 октября 2009

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

...