How to use SUM and COUNT mysql in one query - mysql

Not sure if this is possible but I have the following
SELECT SUM(rating) as rating FROM details WHERE client_id = '$id'
The rating column contains individual ratings of users (1,2,3,4,5) stars. I need to sum them all to be able to calculate the average, but I would also like to get how many stars of each delimiter that user got as well.
For instance
The user has 3 records and the ratings are (3,4,3). With a SUM of 10 out of 3 records, I get 3.3 average. But I would like as well
3 stars = 2
4 stars = 1
Is it possible to do this with one query?

If I got your question right, you can use AVG() function instead of SUM().
In the following query, it calculates the average rating of this client_id, also counts number of each star as required in question.
SELECT
AVG(rating) as rating,
COUNT(CASE WHEN rating=1 THEN 1 END) as star_1,
COUNT(CASE WHEN rating=2 THEN 1 END) as star_2,
COUNT(CASE WHEN rating=3 THEN 1 END) as star_3,
COUNT(CASE WHEN rating=4 THEN 1 END) as star_4,
COUNT(CASE WHEN rating=5 THEN 1 END) as star_5
FROM
details
WHERE
client_id = ID_HERE
GROUP BY
client_id

SELECT client_id ,sum(if(rating='1',1,0)) onestar,sum(if(rating='2',1,0)) twostar,sum(if(rating='3',1,0)) threestar,sum(if(rating='4',1,0)) fourstar,sum(if(rating='5',1,0)) fivestar, SUM(rating) sumrate,AVG(rating) as avgrate FROM details WHERE client_id = '$id'
or for all clients
SELECT client_id ,sum(if(rating='1',1,0)) onestar,sum(if(rating='2',1,0)) twostar,sum(if(rating='3',1,0)) threestar,sum(if(rating='4',1,0)) fourstar,sum(if(rating='5',1,0)) fivestar, SUM(rating) sumrate,AVG(rating) as avgrate FROM details WHERE group by client_id

It is a bit unclear what exactly you are after, but this might work:
SELECT rating, count(rating) FROM details WHERE client_id = '$id' GROUP BY rating;
Also, not sure how you are getting $id, but if you are getting it from the user, you should be using prepared statements rather than inserting it directly in your SQL code.

You don't need to sum your rating. I believe what you want is to key off the rating. I'd suggest this.
This will group every rating then tell you how many times this client is rated something that many times. This would also help you account for any instances where they made a decimal vote (i.e. 4.5 stars)
SELECT
concat(rating, ' Stars') as rating,
count(*) as count
FROM details
WHERE client_id = '$id'
Group by concat(rating, ' Stars');

I think this should do it. Also, you said you're summing them only to take the average. Why not use AVG() instead.
SELECT COUNT(rating), AVG(rating) as rating FROM details WHERE client_id = '$id' GROUP BY rating

Related

Explain SQL "SELECT count(*) FROM t AS 2 WHERE t1.col1 = t2.col1"

Can anyone, please, explain syntax of following request? The question is - if test2 is a result of count function, it is just a number. How can it be treated as a table (revenue.country_code = test2.country_code)? This code works, but I don't understand how. Thanks a lot for any answer.
SELECT customer_user_id, revenue, country_code FROM revenue
WHERE
(SELECT count(*)
FROM revenue AS test2
WHERE revenue.country_code = test2.country_code
AND test2.revenue > revenue.revenue) < 5
and media_source = 'facebook'
ORDER BY country_code, revenue DESC;
This is called a Correlated Subquery. The Subquery contains a reference to the table in the main query in its WHERE clause and it works similar to a join.
What this is saying in english is "We compare the number of records in this table for this country_id that have a higher revenue than this record's revenue. If that count is less than 5, then keep this record".
If it helps to understand, this could also be written with window functions:
SELECT *
FROM
(
SELECT customer_user_id, revenue, country_code
,DENSE_RANK() OVER (PARTITION BY country_code ORDER BY revenue DESC) as revenuerank
FROM revenue
WHERE media_source = 'facebook'
) sub
WHERE sub.revenuerank < 5

How To Find Duplicate, Count and Sum Values from different columns in MySQL?

I have my table
I want to get duplicates from the Name and Status column, count them, and sum values from the Sum column. I want to look like this:
I am new to SQL so that it may be an easy answer, but I can't seem to find a solution.
This is how far I got, but I can't seem to get the count and sum without errors.
SELECT name, COUNT(*) AS recovered
FROM complaints
WHERE status = "Recovered"
GROUP BY name
HAVING COUNT(name) > 0
myQuery
You can do conditional aggregation:
select
name,
sum(status = 'Recovered') recovered,
sum(status = 'Unrecovered') unrecovered,
sum(case when status = 'Recovered' then `sum` end) total_recovered_value,
sum(case when status = 'Unrecovered' then `sum` end) total_unrecovered_value
from mytable
group by name
order by name
Side note: sum is a language keyword, hence not a good choice for a column name.

SQL - COUNT() counts wrong number

I am trying to count the number of profile visits, but it counts the wrong number. In the following example there should be 3 visits, but it counts 6! Anyone know what is wrong with it? http://sqlfiddle.com/#!9/b43ea/8
SELECT *,
COUNT(profile_visitors.profile_id) AS visitorCount
FROM profile_visitors
LEFT JOIN user_login ON user_login.user_id = profile_visitors.user_id
WHERE profile_visitors.user_id = 1
You need to Group By to count multiple rows, So take the Star out of your query and add a group by user_id also make it profile_visitors.*
The LEFT JOIN to user_login table provides no benefit to this question, but, the following query will get you the detail you want to see (assuming you only want to see the number of visits for user_id = 1):
SELECT COUNT(profile_visitors.profile_id) AS visitorCount
FROM profile_visitors
WHERE profile_visitors.user_id = 1
GROUP BY profile_visitors.profile_id
To see all visits by profile use:
SELECT profile_id, COUNT(profile_visitors.profile_id) AS visitorCount
FROM profile_visitors
GROUP BY profile_visitors.profile_id
you can use WHERE IN () to compare if profile_visitors.user_id exist in user_login
SELECT *,
COUNT(profile_visitors.user_id) AS visitorCount
FROM profile_visitors
WHERE profile_visitors.user_id IN (SELECT user_id FROM user_login )
result:
id user_id profile_id visit_date visitorCount
1 1 1 May, 10 2015 15:26:46 3

Error in subquery

im stuck here and i don't know how to fix it.
I have a db table which has users ID, user grade and date when someone has voted for that user (3 fields).
Im trying to read the user that has the highest average grade for todays date, limited to one.
But the problem is that i want to read only users that have 5 or more votes.
My query looks like this, but im getting an error:
SELECT
idusers,
AVG(votes) AS Grade
FROM rank
WHERE (data = '{$dbDate}')
AND ((SELECT count(ID) + 1 FROM rank) AS tmpcount WHERE tmpcount>4)
GROUP BY idusers
ORDER BY Grade DESC
LIMIT 1
Without the tmpcount>4 clause this query is working ok, but I need to count the Id's.
You have to use HAVING to filter the result set on aggregated values such as COUNT (SUM, MIN, MAX, AVG, …):
SELECT idusers, AVG(votes) AS Grade
FROM rank
WHERE (data = '{$dbDate}')
GROUP BY idusers
HAVING COUNT(*) > 4
ORDER BY Grade DESC
LIMIT 1

Getting difference between counts of two subqueries

I'm trying to determine the score of an entry by finding the difference between the number of upvotes and downvotes it has received in MYSQL by running SELECT (SELECT COUNT(vote_id) AS vote_up FROMvotesWHERE vote='UP'),(SELECT COUNT(vote_id) AS vote_down FROMvotesWHERE vote='DOWN'),(vote_up - vote_down AS vote_score). When I try to run this though, it tells me that I do not have proper syntax. What am I doing wrong?
Also, is there a better way to write this?
And finally, what is the ideal way to find the item with the highest and lowest number of votes? Would I just ORDER BY [above query]?
You can do it with
SELECT some_id
, SUM(
CASE
WHEN vote = 'UP'
THEN 1
WHEN vote = 'DOWN'
THEN -1
ELSE 0
END
) as vote_score
FROM votes
GROUP BY some_id
Note that the better approach is to have +1 or -1 stored in vote, then you can just do:
SELECT some_id, SUM(vote) as vote_score
FROM votes
GROUP BY some_id
BTW if my formatting looks odd to you, I explained it in http://bentilly.blogspot.com/2011/02/sql-formatting-style.html.
You can do it by pulling that last clause into a (SELECT ...) block as well:
SELECT
(SELECT COUNT(vote_id) FROM votes WHERE vote='UP') AS vote_up,
(SELECT COUNT(vote_id) FROM votes WHERE vote='DOWN') AS vote_down,
(SELECT vote_up - vote_down) AS vote_score
ORDER BY vote_whatever;
Note btilly's answer about having +/- 1 be the upvote / downvote representation. It makes a lot more sense in this context, and allows for smaller tables, faster comparisons, and use of the SUM() function when necessary:
SELECT SUM(vote) from votes;
Also note: You'll only get vote_up and vote_down counts using the multiple (SELECT ...) method - SUM(CASE) will only give you the total.
Following up on btilly's answer, If you need to know the lowest and highest but do not need to know what ID has the highest/lowest:
SELECT MIN(score), MAX(score)
FROM (
SELECT SUM(IF(vote = 'DOWN', -1, vote = 'UP')) AS score
FROM votes
GROUP BY ID
)
If you do need to know the ID, use the inner query (add the ID to the select) with a ORDER BY score LIMIT 1 to get the lowest and ORDER BY score DESC LIMIT 1 to get the highest.
note in the case of ties, this will choose only 1 of them.