开发者

SQL Server: Having clause with variables

开发者 https://www.devze.com 2023-02-13 06:06 出处:网络
I\'m working on a stored procedure for an academic institution that would allow advisors to filter their student lists by a number of criteria. Recently, the advisors asked me to give them the option

I'm working on a stored procedure for an academic institution that would allow advisors to filter their student lists by a number of criteria. Recently, the advisors asked me to give them the option of filtering students by GPA. This was perfectly easy until they asked for an option to determine the inequality.

Here's a truncated copy of the query I'm using, and the corresponding error message in 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开发者_如何学C) <  @Gpa
        WHEN '<=' THEN SUM(GradePointValue * Credits) / SUM(Credits) <= @Gpa
    END 
ORDER BY GPA desc

When I try to execute this query, SSMS gives me the following error message: Incorrect syntax near '>'., referencing the first line of the CASE statement in the HAVING clause, >= @GPA

I've tried rewriting the HAVING clause to:

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

This produces another error message: Incorrect syntax near the keyword 'CASE'.

I know I could copy and paste the entire SQL query four times and change only the inequality in the HAVING clause in each query, but that's messy (not that this isn't -- it just doesn't smell as bad to me) and I'd like to avoid it if I can. Is there any way for me to pull off my attempt above?


;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) = '<')


You should probably try with -

CASE ''' + @Inequality + '''


You can mimic having multiple WHERE clauses with a CASE statement.

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

You could also do this if you don't want an inline view.

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


Try casting your SUM(GradePointValue * Credits) / SUM(Credits) to a DECIMAL.

0

精彩评论

暂无评论...
验证码 换一张
取 消