SQL Server: предложение с переменными - PullRequest
0 голосов
/ 25 февраля 2011

Я работаю над хранимой процедурой для академического учреждения, которая позволила бы советникам фильтровать свои списки студентов по ряду критериев. Недавно консультанты попросили меня дать им возможность фильтровать студентов по GPA. Это было очень легко, пока они не попросили вариант определения неравенства.

Вот усеченная копия используемого мной запроса и соответствующее сообщение об ошибке в SQL.

DECLARE @Inequality CHAR(2)
SET @Inequality = '>='

DECLARE @Gpa DECIMAL(3,1)
SET @Gpa = 2.0

SELECT DISTINCT
    mem.StudentID,
    SUM(GradePointValue * Credits) / SUM(Credits) AS GPA
FROM <snip>
WHERE <snip>
GROUP BY mem.StudentID
HAVING 
    CASE @Inequality
        WHEN '>=' THEN SUM(GradePointValue * Credits) / SUM(Credits) >= @Gpa
        WHEN '>'  THEN SUM(GradePointValue * Credits) / SUM(Credits) >  @Gpa
        WHEN '<'  THEN SUM(GradePointValue * Credits) / SUM(Credits) <  @Gpa
        WHEN '<=' THEN SUM(GradePointValue * Credits) / SUM(Credits) <= @Gpa
    END 
ORDER BY GPA desc

Когда я пытаюсь выполнить этот запрос, SSMS выдает мне следующее сообщение об ошибке: Incorrect syntax near '>'., ссылаясь на первую строку оператора CASE в предложении HAVING, >= @GPA

Я пытался переписать предложение HAVING на:

HAVING SUM(GradePointValue * Credits) / SUM(Credits)
    CASE @Inequality
        WHEN '>=' THEN >=
        ...
    END @Gpa

Это приводит к другому сообщению об ошибке: Incorrect syntax near the keyword 'CASE'.

Я знаю, что могу копировать и вставлять весь SQL-запрос четыре раза и изменять только неравенство в предложении HAVING в каждом запросе, но это грязно (не то, чтобы это не так - просто не пахнет как плохо для меня) и я хотел бы избежать этого, если смогу. Можно ли как-нибудь осуществить мою попытку выше?

Ответы [ 4 ]

4 голосов
/ 25 февраля 2011
;WITH cte As
(
SELECT /*Don't need DISTINCT with GROUP BY*/
    mem.StudentID,
    SUM(GradePointValue * Credits) / SUM(Credits) AS GPA
FROM <snip>
WHERE <snip>
GROUP BY mem.StudentID
)
SELECT StudentID, GPA
FROM cte WHERE (GPA > @Gpa AND LEFT(@Inequality, 1) = '>')
            OR (GPA = @Gpa AND RIGHT(@Inequality,1) = '=')
            OR (GPA < @Gpa AND LEFT(@Inequality,1) = '<')
1 голос
/ 25 февраля 2011

Возможно, вам стоит попробовать -

CASE ''' + @Inequality + '''
0 голосов
/ 26 февраля 2011

Вы можете имитировать несколько предложений WHERE с помощью оператора CASE.

DECLARE
 @Inequality VARCHAR(2)
,@Gpa FLOAT
SET @Inequality = '>='
SET @Gpa = 2.0


SELECT
 V.StudentID
,V.GPA

FROM (
    SELECT
     mem.StudentID
    ,SUM(GradePointValue * Credits)/SUM(Credits) AS GpaValue

    FROM <snip>

    WHERE <snip>

    GROUP BY mem.StudentID
) AS V

WHERE CASE WHEN @Inequality = '>=' AND V.GpaValue >= @Gpa THEN 1
        WHEN @Inequality = '>' AND V.GpaValue > @Gpa THEN 1
        WHEN @Inequality = '<' AND V.GpaValue < @Gpa THEN 1
        WHEN @Inequality = '<=' AND V.GpaValue <= @Gpa THEN 1
        ELSE 0 END = 1

Вы также можете сделать это, если вам не нужен встроенный просмотр.

SELECT
 mem.StudentID
,SUM(GradePointValue * Credits)/SUM(Credits) AS GpaValue

FROM <snip>

WHERE <snip>

GROUP BY mem.StudentID

HAVING CASE WHEN @Inequality = '>=' AND SUM(GradePointValue * Credits)/SUM(Credits) >= @Gpa THEN 1
        WHEN @Inequality = '>' AND SUM(GradePointValue * Credits)/SUM(Credits) > @Gpa THEN 1
        WHEN @Inequality = '<' AND SUM(GradePointValue * Credits)/SUM(Credits) < @Gpa THEN 1
        WHEN @Inequality = '<=' AND SUM(GradePointValue * Credits)/SUM(Credits) <= @Gpa THEN 1
        ELSE 0 END = 1
0 голосов
/ 25 февраля 2011

Попробуйте привести SUM(GradePointValue * Credits) / SUM(Credits) к DECIMAL.

.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...