Reputation: 634
I have an SQL table named "DATA" as follows:
id plan mode cost. purchaseDate
1. cd3. ANNUALLY 34. 2020-05-04
2. fg45. QUARTERLY 456. 2021-01-02
I'm attempting to return the following 3 columns: plan, planCount, totalCostPerPlan
I've been working a query to return this and so far it looks like this:
SELECT
plan,
COUNT(id) as planCount,
CASE
WHEN mode = 'ANNUALLY' THEN SUM(cost)
WHEN mode = 'S/ANNUALLY' THEN SUM(cost * 2)
WHEN mode = 'QUARTERLY' THEN SUM(cost * 3)
WHEN mode = 'MONTHLY' THEN SUM(cost * 12)
ELSE SUM(cost)
FROM DATA
WHERE purchaseDate >= *not important*
GROUP BY plan, mode
ORDER BY plan ASC
It sort of works, however, I get the data only partially grouped as follows:
plan. planCount. totalCostPerPlan
cd3. 5 *not important*
cd3. 600 *not important*
cd3. 32 *not important*
fg45. 1 *not important*
fg45. 10 *not important*
h100. 7 *not important*
(The table is just an example)
How to I further group by plan? I'm trying to obtain the total value for each plan, however, they're shown with a separate row for each mode. Please assist.
Upvotes: 0
Views: 60
Reputation: 1157
I used your query with few modifications to retrieve the answer. In your query, Near the case statement there was an error and I corrected that by adding end and column name alias. Then I removed Order by as I want to use the result in derived table to group by further. You can use temp table or CTE (Common table Expression) to retrieve the data as well. The answer I added is using Derived table.
DECLARE @table table(id int, [plan] varchar(10), mode varchar(30), cost int, purchaseDate date)
insert into @table
values
(1,'cd3' , 'ANNUALLY' , 34 , '2020-05-04'),
(2,'fg45', 'QUARTERLY', 456, '2021-01-02'),
(3,'cd3' , 'MONTHLY' , 12 , '2020-05-04'),
(4,'fg45', 'QUARTERLY', 40, '2021-01-02')
SELECT
A.[plan]
,SUM(A.[Cost]) AS [Cost]
FROM
(
SELECT
[plan],
COUNT(id) as planCount,
CASE
WHEN mode = 'ANNUALLY' THEN SUM(cost)
WHEN mode = 'S/ANNUALLY' THEN SUM(cost * 2)
WHEN mode = 'QUARTERLY' THEN SUM(cost * 3)
WHEN mode = 'MONTHLY' THEN SUM(cost * 12)
ELSE SUM(cost) END As [Cost]
FROM @table
WHERE purchaseDate >= '2020-05-04'
GROUP BY [plan], mode
) AS A
GROUP BY A.[plan]
Your final result would be something like this: and you can change the query with your tables.
Upvotes: 0
Reputation: 12969
You can go for CROSS APPLY to calculate the new cost for each plan mode. Then, you can go for GROUP BY.
DECLARE @table table(id int, pplan varchar(10), mode varchar(30), cost int, purchaseDate date)
insert into @table
values
(1,'cd3' , 'ANNUALLY' , 34 , '2020-05-04'),
(2,'fg45', 'QUARTERLY', 456, '2021-01-02'),
(3,'cd3' , 'MONTHLY' , 12 , '2020-05-04'),
(4,'fg45', 'QUARTERLY', 40, '2021-01-02')
SELECT tt.pplan, tt.mode, count(tt.id) as countOfPlans, sum(t.newcost) as totalCost
FROM @table as tt
CROSS APPLY
( VALUES( CASE pplan WHEN 'ANNUALLY' THEN cost
WHEN 'QUARTERLY' THEN cost * 3
when 'MONTHLY' THEN cost * 12
else cost
end)) as t(newcost)
group by pplan, mode
pplan | mode | countOfPlans | totalCost |
---|---|---|---|
cd3 | ANNUALLY | 1 | 34 |
cd3 | MONTHLY | 1 | 12 |
fg45 | QUARTERLY | 2 | 496 |
Upvotes: 0
Reputation: 1270091
Hmmm . . . If you want to put factors into the sum()
then the case
is the argument to the sum()
:
SELECT plan, COUNT(id) as planCount,
SUM(CASE WHEN mode = 'ANNUALLY' THEN cost
WHEN mode = 'S/ANNUALLY' THEN cost * 2
WHEN mode = 'QUARTERLY' THEN cost * 3
WHEN mode = 'MONTHLY' THEN cost * 12
ELSE cost
END)
FROM DATA
WHERE purchaseDate >= *not important*
GROUP BY plan
ORDER BY plan ASC
Upvotes: 1