Reputation: 404
I have table like this.
Table 1 :
ID Name s1 s2 s3 id_sub
-----------------------
1 John 90 80 90 1
2 Nick 80 70 90 1
3 Mike 95 95 80 1
4 John 70 70 70 2
Table 2 :
id_sub sub sub_name
---------------
1 ph physic
2 mt math
3 cm chemistry
Query:
SELECT t_score.name, (t_score.s1 + t_score.s2 + t_score.s3) as score
FROM t_score, t_sub
where t_score.id_sub = t_sub.id_sub AND t_score.id_sub = 1
GROUP BY name
I want it return like this
Name score
----------
John 260
Nick 240
Mike 210
But it returns
Column 't_score.s1' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause
Column 't_score.s2' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause
Column 't_score.s3' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause
How to fix it?
[EDIT] i made a mistake on calculate score.
Name score
----------
John 260
Nick 240
Mike 270
score is SUM of each row contains s1+s2+s3
Upvotes: 1
Views: 2471
Reputation: 15977
You can get what you need without GROUP BY and SUM, if you don't have duplicates with same id and name:
;WITH cte AS (
SELECT *
FROM (VALUES
(1, 'John', 90, 80, 90, 1),
(2, 'Nick', 80, 70, 90, 1),
(3, 'Mike', 95, 95, 80, 1),
(4, 'John', 70, 70, 70, 2)
) as t (ID, Name, s1, s2, s3, id_sub)
)
SELECT name,
IsNull(s1,0)+IsNull(s2,0)+IsNull(s3,0) as [score]
FROM cte
WHERE id_sub = 1
Output:
name score
---- -----------
John 260
Nick 240
Mike 270
(3 row(s) affected)
Upvotes: 2
Reputation: 94859
First of all you are using an antiquated join syntax that you shouldn't use anymore. Use explicit joins instead:
FROM t_score
JOIN t_sub ON t_sub.id_sub = t_score.id_sub
Then you join with t_sub, but you select no field from it, so why join at all? Your query could be re-written as:
SELECT name, (s1 + s2 + s3) AS score
FROM t_score
WHERE id_sub = 1
GROUP BY name;
Then you group by name, but you don't say what aggregate on s1 etc. you want to see. Do you want to sum the maximum s1, s2, s3? Or the minimum values? Or the avarages? Probably the sums. Hence:
SUM(s1) + SUM(s2) + SUM(s3)
or simply
SUM(s1 + s2 + s3)
But then: can s1, s2 or s3 be NULL? Then you'd have to deal with that, too:
COALESCE(SUM(s1), 0) + COALESCE(SUM(s2), 0) + COALESCE(SUM(s3), 0)
Here is the final query:
SELECT
name,
COALESCE(SUM(s1), 0) + COALESCE(SUM(s2), 0) + COALESCE(SUM(s3), 0) AS score
FROM t_score
WHERE id_sub = 1
GROUP BY name;
Or is the name in t_score unique (over all records or at least per id_sub)? Then you wouldn't have to aggregate records at all (i.e. no SUM
, no GROUP BY
):
SELECT
name,
COALESCE(s1, 0) + COALESCE(s2, 0) + COALESCE(s3, 0) AS score
FROM t_score
WHERE id_sub = 1;
Upvotes: 1
Reputation: 13700
Use SUM function
SELECT t_score.name, SUM(t_score.s1 + t_score.s2 + t_score.s3) as score
FROM t_score, t_sub
where t_score.id_sub = t_sub.id_sub AND t_score.id_sub = 1
GROUP BY name
Upvotes: 3
Reputation: 72165
Use SUM
:
SELECT t_score.name, SUM(t_score.s1 + t_score.s2 + t_score.s3) as score
FROM t_score
INNER JOIN t_sub ON t_score.id_sub = t_sub.id_sub
WHERE t_score.id_sub = 1
GROUP BY name
Also, it is preferable to use explicit join syntax, as in the above query.
Upvotes: 4