I'm trying to use a calculated column in a where clause.
I've trying everything from CROSS APPLY, to sub-query select but it does not give me the anything near what I need.
My query so far:
SELECT p.Code, c.AccountNumber, Sales = (SUM(p.UnitPrice) * SUM(od.QtyShipped)) FROM [dbo].Customer c
LEFT JOIN [dbo].OrderHeader oh ON oh.CustomerId = c.Id
LEFT JOIN [dbo].OrderDetail od ON od.OrderHeaderId = oh.Id
LEFT JOIN [dbo].Product p ON p.Id = od.ProductId
WHERE Sales > 100
GROUP BY p.Code, c.AccountNumber, Sales
This does not work, as 'Sales' is an invalid column
Standard SQL disallows references to column aliases in a WHERE clause.
You can't use window functions in WHERE , because the logical order of operations in an SQL query is completely different from the SQL syntax. The logical order of operations in SQL is: FROM, JOIN.
But the WHERE.. IN clause allows only 1 column.
Using Derived Columns in a predicate
You'll need to wrap the inner query in a derived table or CTE in order to be able to use derived columns in the WHERE
clause (Also, note SUM()
is specified just once, using the results of the multiplication):
SELECT x.Code, x.AccountNumber, x.Sales
FROM
(
SELECT p.Code, c.AccountNumber, SUM(p.UnitPrice *od.QtyShipped) AS Sales
FROM [dbo].Customer c
LEFT JOIN [dbo].OrderHeader oh ON oh.CustomerId = c.Id
LEFT JOIN [dbo].OrderDetail od ON od.OrderHeaderId = oh.Id
LEFT JOIN [dbo].Product p ON p.Id = od.ProductId
GROUP BY p.Code, c.AccountNumber
) AS x
WHERE x.Sales > 100;
Repeating the Derived Column in a HAVING clause
As per @Jonny's comment, the other way is not to DRY up the calculated column, but to instead repeat the calculation. Use HAVING
instead of WHERE
after a GROUP BY
has been applied.
SELECT p.Code, c.AccountNumber, SUM(p.UnitPrice *od.QtyShipped) AS Sales
FROM [dbo].Customer c
LEFT JOIN [dbo].OrderHeader oh ON oh.CustomerId = c.Id
LEFT JOIN [dbo].OrderDetail od ON od.OrderHeaderId = oh.Id
LEFT JOIN [dbo].Product p ON p.Id = od.ProductId
GROUP BY p.Code, c.AccountNumber
HAVING SUM(p.UnitPrice * od.QtyShipped) > 100;
In either case, as per comments below, note that the calculated expression is SUM(p.UnitPrice * od.QtyShipped)
and not SUM(p.UnitPrice) * SUM(od.QtyShipped)
.
You can use the common table expression for this
;WITH CTE AS
(
SELECT p.Code, c.AccountNumber, Sales = (SUM(p.UnitPrice) * SUM(od.QtyShipped)) FROM [dbo].Customer c
LEFT JOIN [dbo].OrderHeader oh ON oh.CustomerId = c.Id
LEFT JOIN [dbo].OrderDetail od ON od.OrderHeaderId = oh.Id
LEFT JOIN [dbo].Product p ON p.Id = od.ProductId
GROUP BY p.Code, c.AccountNumber, Sale
)
SELECT *
FROM CTE WHERE CTE.Sales>100
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With