Grouping on an expression (and possible HAVE) I have the following query, which I rewrote as a 'simple' example below.

The expression CONVERT(int, RTRIM(' ' + UPPER(CONVERT(char, a+b))))/c is just a weird example of a complex function.

I am questioning myself:
 Why do I have to put this complex expression 3 times in my query?

DROP TABLE #TEMP
CREATE TABLE #TEMP (a int, b int, c int)

INSERT INTO #TEMP VALUES( 1,1,1)
INSERT INTO #TEMP VALUES( 1,1,2)
INSERT INTO #TEMP VALUES( 1,1,3)
INSERT INTO #TEMP VALUES( 1,2,1)
INSERT INTO #TEMP VALUES( 1,2,2)
INSERT INTO #TEMP VALUES( 1,2,3)
INSERT INTO #TEMP VALUES( 2,1,1)
INSERT INTO #TEMP VALUES( 2,1,2)
INSERT INTO #TEMP VALUES( 2,1,3)
INSERT INTO #TEMP VALUES( 2,2,1)
INSERT INTO #TEMP VALUES( 2,2,2)
INSERT INTO #TEMP VALUES( 2,2,3)



SELECT 
    a,
    b,
    CONVERT(int, RTRIM(' ' + UPPER(CONVERT(char, a+b))))/c as d
from #TEMP
GROUP BY a, b, CONVERT(int, RTRIM(' ' + UPPER(CONVERT(char, a+b))))/c
HAVING CONVERT(int, RTRIM(' ' + UPPER(CONVERT(char, a+b))))/c &gt;= 0
ORDER BY 3 DESC


The question is mainly for using in SQL Server, but answers for other database management systems are welcome too.
You don't have to.  You can just rewrite it to CTE/inline view , and refer by alias :

SELECT t.* FROM 
(
SELECT 
    a,
    b,
    CONVERT(int, RTRIM(' ' + UPPER(CONVERT(char, a+b))))/c as d
from #TEMP
)t
GROUP BY a,b,d
HAVING d &gt; 0 
ORDER BY 3 ;


or 

WITH cte1 AS 
(
SELECT 
    a,
    b,
    CONVERT(int, RTRIM(' ' + UPPER(CONVERT(char, a+b))))/c as d
from #TEMP
)
select t.* 
from cte1 t
group by t.a,t.b,t.d 
having t.d &gt; 0 
order by 3; 


Also, there is no need for  GROUP BY( and HAVING can be replaced by WHERE)  in this particular case - SELECT DISTINCT will do the job.