Reputation: 3618
;WITH CTE AS
(
SELECT * FROM
(
SELECT CandidateID, t_Candidate.Name, ISNULL(CAST(AVG(Rate) AS DECIMAL(12,2)),0) AS Rate, t_Ambassadors.Name AS CN
FROM t_Vote INNER JOIN t_Candidate
ON t_Vote.CandidateID = t_Candidate.ID
INNER JOIN t_Ambassadors
ON t_Vote.AmbassadorID = t_Ambassadors.ID
GROUP BY Rate, CandidateID, t_Candidate.Name, t_Ambassadors.Name
)MySrc
PIVOT
(
AVG(Rate)
FOR CN IN ([Jean],[Anna],[Felicia])
)AS nSrc
)SELECT CandidateID, Name, CAST([Jean] AS DECIMAL(12,2)) AS AHH ,CAST([Anna] AS DECIMAL(12,2)) AS MK,CAST([Felicia] AS DECIMAL(12,2)) AS DIL, CAST(([Jean] + [Anna] + [Felicia])/3 AS DECIMAL(12,2)) AS Total
FROM CTE
GROUP BY Cte.CandidateID, cte.Name, cte.[Jean], cte.[Anna], cte.[Felicia]
I have solved my previous problem with the above query. I created a new question because I have new problem. How do I get the MAX and MIN rate in a row?
The following is the result I get from the above query:
| CandidateID | Name | AHH | MK | DIL | Total |
|-------------|------|-------|------|------|-------|
| CID1 | Jay | 7.00 | 3.00 | 3.00 | 4.33 |
| CID2 | Mia | 2.00 | 9.00 | 7.00 | 6.00 |
What I want to achieve is this:
| CandidateID | Name | AHH | MK | DIL | Total |
|-------------|------|-------|------|------|-------|
| CID1 | Jay | 7.00 | 3.00 | 3.00 | 3.00 |
| CID2 | Mia | 2.00 | 9.00 | 7.00 | 7.00 |
So what happened on the 2nd result is that, it removed the Highest and Lowest score/rate from the row and Get the average of remaining rate/score. AHH, MK and DIL are not the only Voters, there are 14 of them, I just took the 3 first to make it short and clearer.
Upvotes: 4
Views: 110
Reputation: 2874
I believe you're looking by something like the following (though I'm using case aggregation rather than a pivot).
Essentially, it does the same thing your query does except that it uses a row number to figure out the highest and lowest and exclude them from the final "total" (in the case of a tie, it'll just select one of them, but you can use RANK()
instead of row_number() if you don't want to include tied highest/lowest in the average):
WITH CTE AS
(
SELECT CandidateID,
Name,
CN,
Rate,
Lowest = ROW_NUMBER() OVER (PARTITION BY CandidateID, Name ORDER BY Rate),
Highest = ROW_NUMBER() OVER (PARTITION BY CandidateID, Name ORDER BY Rate DESC)
FROM
(
SELECT CandidateID,
t_Candidate.Name,
CN = t_Ambassadors.Name,
Rate = ISNULL(CAST(AVG(Rate) AS DECIMAL(12,2)),0)
FROM t_Vote
JOIN t_Candidate
ON t_Vote.CandidateID = t_Candidate.ID
JOIN t_Ambassadors
ON t_Vote.AmbassadorID = t_Ambassadors.ID
GROUP BY CandidateID, t_Candidate.Name, t_Ambassadors.Name
) AS T
)
SELECT CandidateID,
Name,
AHH = MAX(CASE WHEN CN = 'Jean' THEN Rate END),
MK = MAX(CASE WHEN CN = 'Anna' THEN Rate END),
DIL = MAX(CASE WHEN CN = 'Felicia' THEN Rate END), -- and so on and so forth for each CN
Total = AVG(CASE WHEN Lowest != 1 AND Highest != 1 THEN Rate END)
FROM CTE
GROUP BY CandidateID, Name;
EDIT: It is possible to do this using PIVOT, but unless I'm mistaken, it becomes a matter of working out the average of the ones that aren't highest and lowest before pivoting, which becomes a bit more convoluted. It's all around easier to use case aggregation, IMO.
Upvotes: 3