Reputation: 11
I was looking for help in the error I get in SQL Server when I try run this query.
The query is just for splitting the products to 4 groups by 2 conditions (the quantity and the revenue). For the revenue I need the SUM
function, and that's causing me problems in the GROUP BY
(if I understood the error well).
How can I solve this problem?
Select
CASE
WHEN Ord1.Quantity<10 OR SUM(Ord1.Quantity*Ord1.UnitPrice)<50000 THEN
'Risky Product'
WHEN Ord1.Quantity<30 OR SUM(Ord1.Quantity*Ord1.UnitPrice)<250000 THEN
'Fair Product'
WHEN Ord1.Quantity<60 OR SUM(Ord1.Quantity*Ord1.UnitPrice)<750000 THEN
'Normal Product'
Else 'Great Product'
End As 'Group', SUM(Ord1.Quantity*Ord1.UnitPrice)
From (Select OD.ProductID,OD.Quantity,OD.UnitPrice
From [Order Details] As OD INNER JOIN Orders As O
ON O.OrderID=OD.OrderID
Where DATEPART(YEAR,O.OrderDate)=1997) As Ord1
Group By
CASE
WHEN Ord1.Quantity<10 OR SUM(Ord1.Quantity*Ord1.UnitPrice)<50000 THEN
'Risky Product'
WHEN Ord1.Quantity<30 OR SUM(Ord1.Quantity*Ord1.UnitPrice)<250000
THEN 'Fair Product'
WHEN Ord1.Quantity<60 OR SUM(Ord1.Quantity*Ord1.UnitPrice)<750000 THEN
'Normal Product'
Else 'Great Product'
End
Upvotes: 1
Views: 319
Reputation: 2862
You have confirmed my suspicion. And I'll respond with - no point in correcting a query that is logically flawed at the beginning. You need to aggregate BEFORE you categorize. Your original approach was attempting to do both. So start over. Typically it is easier to break your problem into pieces that can be accomplished - you start at the basic level of just selecting rows, then you modify that code step-by-step to build the logic that will achieve your goal. That's appropriate for any language.
So here is my shot at an abbreviated solution. Since you did not provide a schema or data, I used AdventureWorks. In the future, help is more likely to be provided and useful when you provide schema and data or use a standard sample database.
with cte as (
select det.ProductID, sum(det.OrderQty * det.UnitPrice) as totalvalue
from Sales.SalesOrderDetail As det
where exists (
select * from Sales.SalesOrderHeader as ord
where det.SalesOrderID = ord.SalesOrderID
and ord.OrderDate >= '20130101' and ord.OrderDate < '20140101'
)
group by det.ProductID
)
select cte.ProductID, cte.totalvalue,
case when totalvalue >= 75000 then 'Great Product'
else 'meh - needs work' end
as [Group]
from cte
order by [Group], cte.ProductID
;
Pay attention to the where clause in the cte. It is better to avoid applying a function to a column when using that as a filter since a function will prevent the use of any helpful indexes. Note also that I left out most of your logic. This demonstrates the technique; you will need to expand it for your actual needs.
Upvotes: 1