Firstly, to repeat a lot of my comments.
Don't use literal strings for aliases; this is a bad habit and it doesn't work as people think. Take the query SELECT [name] AS 'DatabaseName' FROM sys.databases ORDER BY 'DatabaseName'; This does not ORDER BY the column aliased as 'DatabaseName', instead it orders by the literal varchar value 'DatabaseName'; thus is has no order, as the literal value is the same for every row. Ideally, don't use object and aliases that require delimit identifying. If you must then either use T-SQL's delimit identify, brackets ([]), or the ANSI-SQL delimit identifier, double quotes (").
Next, you can't reference a column by it's alias in the same query scope apart from in the ORDER BY; SELECT 1 AS A, A + 1 AS B; will give an invalid column error, as the column A isn't defined. You would need to repeat the expression again to use that expression in the same scope. If you need to reference a column by its alias, you need to use a derived table or a CTE:
--Derived table
SELECT A,
A + 1
FROM (SELECT 1 AS A) DT;
--CTE
WITH CTE AS (
SELECT 1 AS A)
SELECT A,
A+1 AS B
FROM CTE;
Finally, DateE BETWEEN '05/07/2022' AND '05/07/2022 23:59:59' is bad for a couple of reasons; it misses off the last second of the day, and its an ambiguous date format. Use >= and < logic and an unambiguous format; for T-SQL that is yyyyMMdd and yyyy-MM-ddThh:mm:ss(.nnnnnnn). So instead you have DateE >= '20220705' AND DateE < '20220706'.
Now, onto your problem. As I mentioned, there are a couple of options open to use. Personally, I would suggest just repeating the expressions here, as they aren't complicated:
SELECT NumeroD AS Bill, --Don't use literal strings for aliases
Descrip1 AS ProductDescription, --Don't use object names/aliases that require delimit
MAX(ExistAnt) AS [Ex. Act.], --If you must, then use brackets ([]) or double quotes (")
MIN(ExistAnt) AS [Ex. Act.], --but, ideally use camelCase, PascalCase, or snake_case instead (I prefer PascalCase)
--The above 2 columns have the same alias; that can't be right
SUM(CASE WHEN TipoFac = 'A' THEN Amount
WHEN TipoFac = 'B' THEN -Amount
END) AS TotalAmount,
CASE WHEN TipoFac = 'A' THEN (Amount*Price) END AS TotalSale,
CASE WHEN TipoFac = 'A' THEN (Amount*Cost) END AS TotalCost,
CASE WHEN TipoFac = 'A' THEN (Amount*Price) - (Amount*Cost) END AS TotalUtility, --Repeat the expression
CASE WHEN TipoFac = 'A' THEN (((Amount*Price) - (Amount*Cost)) * 100) / (Amount*Price) END AS PercentageUtil,
NroLineaC,
DEsComp
FROM dbo.SAITEMFAC --Always schema qualify your objects
WHERE DateE >= '20220705' AND DateE < '20220706' --Use better date boundaries, not BETWEEN
AND codubic = '0010-01'
AND CodItem = '11001'
GROUP BY Coditem,
NumeroD,
Descrip1,
TipoFac,
Cantidad,
Precio,
Costo;
If you "had to" reference them by their alias, or for more complicated expressions, I would use a CTE. This isn't needed for what you have here, but I'll show you anyway. As you have a nested reference, you'll actually need to use two CTEs:
WITH SalesCost AS(
SELECT NumeroD AS Bill,
Descrip1 AS ProductDescription,
MAX(ExistAnt) AS ExAct1,
MIN(ExistAnt) AS ExAct2, --These cannot have the same name in a CTE/Derived table
SUM(CASE WHEN TipoFac = 'A' THEN Amount
WHEN TipoFac = 'B' THEN -Amount
END) AS TotalAmount,
CASE WHEN TipoFac = 'A' THEN (Amount*Price) END AS TotalSale,
CASE WHEN TipoFac = 'A' THEN (Amount*Cost) END AS TotalCost,
NroLineaC,
DEsComp
FROM dbo.SAITEMFAC --Always schema qualify your objects
WHERE DateE >= '20220705' AND DateE < '20220706' --Use better date boundaries, not BETWEEN
AND codubic = '0010-01'
AND CodItem = '11001'
GROUP BY Coditem,
NumeroD,
Descrip1,
TipoFac,
Cantidad,
Precio,
Costo),
Utility AS(
SELECT Bill,
ProductDescription,
ExAct1,
ExAct2,
TotalAmount,
TotalSale,
TotalCost,
TotalSale - TotalCost AS TotalUtility, --No need for the CASE here, as it's already handled
NroLineaC,
DEsComp
FROM SalesCost)
SELECT Bill,
ProductDescription,
ExAct1,
ExAct2,
TotalAmount,
TotalSale,
TotalCost,
TotalUtility,
(TotalUtility * 100) / TotalSales AS PercentageUtility,
NroLineaC,
DEsComp
FROM Utility;
') for aliases. Single quotes are for literal strings, not delimit identifying object names. They only work when you define them, no where else;ORDER BY 'value'would not order by a column aliased as'value', it would order by thevarcharliteral'value'(so would effectively not order at all). Also some syntaxes with literal string aliases are deprecated. Stick to object and alias names that don't need delimit identifying, and if you must delimit identify them use the T-SQL identifier, brackets ([]), or ANSI-SQL's, double quotes (").SELECT 1 AS A, A + 1 AS B;will return the errorInvalid column name 'A'., not1and2.SELECT A, A + 1 FROM (SELECT 1 AS A) DT;would work fine though.DateE BETWEEN '05/07/2022' AND '05/07/2022 23:59:59'; in this case it'll exclude any rows after2022-07-05T23:59:59.0000000and before2022-07-06T00:00:00.0000000; so almost an entire second of time. Use>=and<logic for explicit boundaries, notBETWEEN, and don't use ambiguous date formats in your literal strings:DateE >= '20220705' AND DateE < '20220706'