Understanding simple count logic in sql - mysql

I have a very basic question which I cannot answer myself but shouldn't take much of your time.
The following query works, it lists all the exhibition_category_id and counts the total of objects that are assigned to each category.
My question is: Why does it do it? I don't understand the query. It says count(*) - why doesn't it give me the total of different exhibition_category_id's (79), but instead counts, how many objects are assigned to each category?
Here is the query in question, as well as a screen shot from the actual output:
SELECT eb.exhibition_category_id, count(*) AS total
FROM exhibition_brand eb
GROUP BY eb.exhibition_category_id
https://i.stack.imgur.com/6deMv.png
Hope its understandable what I am asking for, eager to improve my post based on feedback.
Cheers

Your query is a basic aggregation query:
SELECT eb.exhibition_category_id, count(*) AS total
FROM exhibition_brand eb
GROUP BY eb.exhibition_category_id;
The GROUP BY specifies that the result set will contain one row for each value of eb.exhibition_category_id. The result set consists of two columns, one is the value that defines the row. The other is a count of the number of rows in each group. That is what COUNT(*) does.
If you wanted the total count of different eb.exhibition_category_id, then you want one row and COUNT(DISTINCT):
select count(distinct eb.exhibition_category_id)
from exhibition_brand eb;

The GROUP BY function groups the COUNT() by eb.exhibition_category_id, so the query groups the records by eb.exhibition_category_id, then counts the corresponding records.

Related

Different output when I include more columns to the select statement in MySQL

Why do I not get the same results when running the two queries? If I run the second one I get the course with the smallest amount of credits and when I run the first one I get the courses ordered by courseid
select min(credits), title, courseid
from course
group by title, courseid
select min(credits)
from course
An aggregation query is any query that has a group by or an aggregation function in the select.
An aggregation query returns one row per group, where a "group" is defined as the unique combination of values of the keys in the group by clause. If there is no group by clause, then all rows are taken to be a single group and one row is returned.
So, your first query returns one row for each combination of title and courseid in the course table. That row contains the minimum value of credits for that combination. If the course table has only one row per courseid, then the results are very similar to the contents of the table.
The second query returns one row overall, with the minimum number of credits of all rows.
If you want to get one row from with the minimum number of credits, then you don't want an aggregation query. Instead, you can use:
select c.*
from course c
order by c.credits
limit 1;
When you use a group by, you are using a sort of "filter", in the first query you group by title, then all the same titles are grouped by courseid, in the second you only select the minimum value of credits without filtering.
Take a look at a group by doc maybe with some graphical examples like this:
https://www.geeksforgeeks.org/sql-group-by/

SUM of column that has been GROUPED BY

I am using the following query:
SELECT mgap_growth
FROM mgap_orders
WHERE account_manager_id = '159795'
GROUP BY mgap_ska_report_category
mgap_growth is a column with identical amounts that differ only per mgap_ska_report_category, which is the reason for the grouping. Now hat I have normalized the individual amounts per category, how can I use SUM to tally their total?
Here is a screenshot of the data:
I only need the SUM of the growth amounts per category, not of all of the mgap_growth records, but Im unsure as to how to SUM after the grouping.
Thanks!
EDIT FOR ADDITIONAL QUERY:
Let me throw another issue into the mix: we know I need to SUM only once per category, but what if I needed to GROUP BY CUSTOMER? I just found out that there are multiple customers in the data, each is duplicated per growth record, but differ by category. I really need to use two groupings, one for category to single out and SUM the growth amount and then another the single out the customer.
Here is an image describing the data:
If I understand you correctly, you need to sum the results from the subquery.
SELECT SUM(mgap_growth) AS total_mgap_growth
FROM (SELECT mgap_growth
from mgap_orders
WHERE account_manager_id = '159795'
GROUP BY mgap_ska_report_category) AS x
This should should show the total growth per category for that particular account manager:
SELECT sum(mgap_growth) AS Growth, mgap_ska_report_category as Category
FROM mgap_orders
WHERE account_manager_id = '159795'
GROUP BY mgap_ska_report_category
Rather than thinking of doing the SUM after the grouping, you can do the two together in the one statement. You were 99% of the way there with what you had already.
To answer your additional question in the comment, you can add another column to group by. The order that you list them in the group by section is the important part. The overall grouping comes first. So assuming 'Customer' is the customer column name you would do this:
SELECT mgap_ska_report_category as Category, Customer, sum(mgap_growth) AS Growth
FROM mgap_orders
WHERE account_manager_id = '159795'
GROUP BY mgap_ska_report_category, customer
WITH ROLLUP
Note that changing the SELECT columns in the top line was just for aesthetics, you can put them in any order and will get the same data, but this will be the easiest to read.
This shows the growth per customer by category for that particular account manager.
Edited again to add WITH ROLLUP. This will give you the totals per category as well. Try it with and without the WITH ROLLUP to see the how it changes things.

Count rows where user has multiple rows

I have a table of transactions that records the person that made the purchase. I want the number of people that have had more than one transaction. The part I became stuck at is how do I specify that Member must match at least twice (e.g. two or more transactions)?
I figured it'd be something along the lines of
SELECT COUNT(*) FROM `table` WHERE COUNT(`Member`)>2
but I realize that isn't a proper usage of the second count.
To further clarify: I want the result to be a single row that contains the number of users that this condition matches. So I don't want it to return how many times it matches per user or anything like that.
you need to use GROUP BY and HAVING.
SELECT COUNT(*) totalMember
FROM
(
SELECT Member
FROM `table`
GROUP BY Member
HAVING COUNT(Member) > 2
) a

Needing some explanation of a MySQL ranking query

I'm hoping to get some explanation on a ranking query I've come across. I have a similar setup where I've got a points field that I want to order by, but can't for the life of my understand this query: http://www.artfulsoftware.com/infotree/queries.php#460
I don't understand what the join is actually doing, and why if I don't include the group by statements, I just get one record that is completely jumbled and incorrect. I always see Group By statements as limiting the number of results, but this query seems to be adding them to the final results set (as without the group by, you get one row returned)
The query is essentially doing this:
For each row in the original votes table, count how many rows (in the same table) have votes <= to that row. The count is the same as the rank.
The JOIN is needed to link the votes table to each individual row in the votes table.
GROUP BY is needed when you have a COUNT() in your select list. For each person, the query is counting how many rows it finds that have votes <= for each person. The GROUP BY with the COUNT is limiting the number of results of the JOIN results which is a multiplication of the original votes table.

SQL combine COUNT and AVG query with SELECT

I need to get the average rating and the total number of ratings for a particular user and then select all single ratings (rating_value, rating_text, creator) as well:
$rating_query = mysql_query("SELECT COUNT(1) as rating_count
,AVG(rating_value), rating_value, rating_text, creator
FROM user_rating WHERE rated_user = $user_id");
This query would return the COUNT(1) result and the AVG(rating_value) for every row, but I only need those values once.
Is there any way to do this without making 2 separate queries?
There may be a trick I'm not aware of, but I don't think that's possible to do in a single query. You could try using a GROUP BY clause if that would make sense for you, but I'm guessing it probably doesn't from the column names you're using. Any relation requires a single atomic value at any given row and column, even if that value is null. What you are requesting is that columns 1 and 2 in every row but the first have no value, and again I don't think this is possible.