Reputation: 365
I have to group the BaseIncidencia
column (sum the values), but it is unavailable. As said in SQL Server AS statement aliased column within WHERE statement it would be simple, but i don't have a column name to refer to. Only the alias.
BEGIN
SELECT @Artigo AS Artigo, T1.Contrib AS ContribID, YEAR(T1.Data) AS Ano, T3.DescricaoMes, CAST(ROUND(SUM(T1.Debito/0.23),2) AS decimal(16,2)) BaseIncidencia,
CAST(ROUND(SUM(T1.Debito),2) AS decimal(16,2)) AS IVA, (CASE WHEN T5.Valid = 'True' THEN 'VALIDO' WHEN T5.Name = '---' THEN 'INEXISTENTE' ELSE 'INVALIDO' END) AS 'ValidadeNIF'
FROM
#CONTAS_INI AS T1
LEFT JOIN
db.dbo.VatCheck T5
ON T1.ContribuinteID = T5.VatNumber
LEFT JOIN
#Meses AS T3
ON MONTH(T1.Data) = T3.Mes
GROUP BY T1.CntID, T1.ContribuinteID, YEAR(T1.Data), (CASE WHEN T5.Valid = 'True' THEN 'VALIDO'
WHEN T5.Name = '---' THEN 'INEXISTENTE' ELSE 'INVALIDO' END), T3.DescricaoMes
ORDER BY (CASE WHEN T5.Valid = 'True' THEN 'VALIDO' WHEN T5.Name = '---' THEN 'INEXISTENTE' ELSE 'INVALIDO' END), T1.ContribuinteID
END
I tried replacing the following line:
GROUP BY T1.CntID, T1.ContribuinteID, YEAR(T1.Data), (CASE WHEN T5.Valid = 'True' THEN 'VALIDO'
With:
GROUP BY T1.CntID, T1.ContribuinteID, YEAR(T1.Data), CAST(ROUND(SUM(T1.Debito/0.23),2) AS decimal(16,2)), (CASE WHEN T5.Valid = 'True' THEN 'VALIDO'
Only to get the Cannot use an aggregate or a subquery in an expression used for the group by list of a GROUP BY clause.
error.
So my question is, why i can't include BaseIncidencia
alias in GROUP BY? And what's the workaround?
Upvotes: 0
Views: 868
Reputation: 752
Reposting 12th Dec.'s comment as an answer.
You'll probably want to wrap your original SELECT ... FROM ...
with SELECT * FROM ( /*your original half*/ ) AS T
, leaving the GROUP ... ORDER ...
parts to come after. This will allow you to reference any aliases produced at your inner SELECT
in your GROUP ... ORDER ...
parts.
However, since the GROUP
moves to a different level, you'll have to move the aggregations like SUM
to the new level as well. Also, you'll lose direct access to your tables, so mostly likely you'll have to change table aliases used in GROUP ... ORDER ...
segments to T
, plus making sure all columns the GROUP ... ORDER ...
parts are using are produced in the inner SELECT
. All this should be easy to handle though.
Upvotes: 0
Reputation: 4439
You can't group by the expression because it is an aggregate. The group by values are used to determine the level at which an aggregate operates.
As a simplied example:
Select Count(*),
Object_id
From sys.columns
Group by Object_id
This is fairly easy to understand. Count the number of column records for each object_id.
What you are trying to do would be the equivalent of
SELECT COUNT( * ),
object_id
FROM sys.columns
GROUP BY COUNT( * ),
object_id
For the count of each object_id, give me the count of each object_id. That doesn't make sense.
The error message you're getting:
Cannot use an aggregate or a subquery in an expression used for the group by list of a GROUP BY clause
is telling you that you can't group by an aggregate expression.
Upvotes: 0
Reputation: 108
SQL is implemented as if a query was executed in the following order:
For most relational database systems, this order explains which names (columns or aliases) are valid because they must have been introduced in a previous step.
So in SQL Server, you cant use a term in the GROUP BY clause that you define in the SELECT clause because the GROUP BY is executed before the SELECT clause.
Upvotes: 3