MySQL get totals from grouped value - mysql

I have a table that's setup like this:
**user_items**
user_item_id
user_id
item_id
User's can have the same item_id associated. If I want to see as a whole, how many items there are assigned to users, this is simply a count.
However, I'd like to the total count factoring in distinct item_id's. So grouping by the item_id, but as a total.
Any idea how I can do this?
Thank you

Select count(*) from ...
is what you are looking for
EDIT: I'm sorry.. This is indeed wrong.
There must be an easier solution, but this will do what you want:
select count() from (select count() from YOURTABLE group by YOURCOL) as WHATEVER;
This counts the rows in the resulting table of the inner query.

Related

How to create MySQL nested query with DISTINCT and COUNT

I have one mySQL table here with some data.
Before asking for help I tried MySQL Nested Select Query? before, but it's not working for me.
So, what I want to do is to list the total of the dir_id with more doc_id. The table should have only two columns as a result. dir_id and total. In this case, the table results shall have for the 1st-row dir_id = 3 and total = 3. In other words, dir_id 3, has 3 doc_id.
I tried to make use of DISTINCT and COUNT to construct a nested query as follow:
SELECT COUNT(*), AS total `dir_id`
FROM
(SELECT DISTINCT dir_id, doc_id
FROM `dir_subdir`
ORDER BY `dir_subdir`.`dir_id` DESC)
Here is the message error I got after running the query. Unfortunately, it is not clear for me, so I cannot fix it.
Any help will be grateful. Thank you!
You're missing GROUP BY dir_id. You also have the comma misplaced.
You can do this without the subquery using COUNT(DISTINCT column)
SELECT dir_id, COUNT(DISTINCT doc_id) AS total
FROM dir_subdir
GROUP BY dir_id
ORDER BY dir_id DESC

MySQL: normalize column from big subquery

I have a very big subquery:
(SELECT Id, Count [...] FROM Something) Counts
I want to create a score for each Id that is the count divided by the max count.
I tried:
SELECT Id, Count/(SELECT MAX(Count)) AS Score
FROM (SELECT Id, Count [...] FROM Something) Counts
But this only returns the first row!
If I do a GROUP BY Id, all scores are equal to 1 (because the maximum is taken for each Id, and not for all Ids).
Do you know what I can do please? I know that in some contexts we can embed a subquery in a WITH clause, but this is not valid in MySQL.
I believe this is what you need:
Select Id, (Count/(SELECT MAX(Count) FROM Something)) As [Score] FROM Something
Explanation:
I believe you want to take max of all counts in the table. In order to do so you need to perform a subquery on the entire set of the table, versus limiting it to a specific id, or grouping it. When you performed your group by operating on ID, assuming each Id is unique, it is effectively returning Id, Count/Count. As you know any non-zero number divided by itself is 1.

How does adding GROUP BY or DISTINCT give the same result set?

SELECT unit.id,
unit.unit_name,
unit.description,
unit.category_id,
city.name,
mealbase.name AS mealbase_name,
unit.province_id,
unit.rooms,
unit.max_people,
unit.thumblocation,
prices.normal_price,
prices.holiday_price
FROM jos_units AS unit,
jos_prices AS prices,
jos_cities AS city,
jos_meal_basis AS mealbase
WHERE prices.unit_id = unit.id
AND city.id = unit.city_id
AND unit.published = 1
AND unit.mealbasis_id = mealbase.id
When I run this query It gives me redundant result set as below.
But If I add
SELECT DISTINCT unit.id Instead of SELECT unit.id at the beginning Or
GROUP BY unit.unit.id at the end. It gives me correct result set as below.
My issue is What's wrong with my query(join above gives redundant result even I have corrected joined them)? Why does the adding SELECT DISTINCT unit.id or GROUP BY unit.unit.id is same for the query(which fixes the issue) here? (DISTINCT AND GROUP BY are different functionalities)
Given that I know adding `SELECT DISTINCT unit.id will remove the redundant results but how does the adding one of the two snippet gives same result set? Obviously SELECT DISTINCT unit.id should remove redundant rows by how does the GROUP BY do it?
Basically you are grouping the results without using an aggregation function (using a COUNT, or a MAX, for examples), thus you get the aggregate row in the same way you would obtain it by selecting DISTINCT objects. If you don't need to aggregate them, DISTINCT is the right thing to do.
join above gives redundant result even I have corrected joined them
why is it?
Thats because of how your tables:
jos_units.
jos_prices.
jos_cities.
jos_meal_basis.
are related to each others.
It seems like you have one to many or many to many relations between those tables. For instance, for each record in the jos_meal_basis, each meal has a unit, so many meals might be measured by the same unit, then when joining the two tables you will get redundant units because of this. The same with other tables.
Your combination in the first query, ie
(unit.id,
unit.unit_name,
unit.description,
unit.category_id,
city.name,
mealbase.name AS mealbase_name,
unit.province_id,
unit.rooms,
unit.max_people,
unit.thumblocation,
prices.normal_price,
prices.holiday_price) has duplicates and so you are getting more than 1 rows for the same combination.
When you use distinct clause or group by it removes duplicates in your above combination. Hope this helps you.
GROUP BY is primarily used if you want to use aggregate or group functions. For example if you wanted to find the number of rows that match you could do
SELECT
id
, COUNT(id) num_rows
FROM
...
GROUP BY id
because the COUNT is an aggregate function you need to group by the other columns. If you aren't doing any aggregate functions, GROUP BY is essentially just aggregating the rows up (if that's the way you've written it) causing only one row - the same as DISTINCT.

Is it wrong to have count(*) as part of the select query

select id, first_name, count(*) from users;
The users table contains 10 entries, but the above select query shows only a single row. Is it wrong to mix count(*) as part of the above query?
COUNT is a function that aggregates. You can't mix it into your normal query.
If you want to receive the ten entries just do a normal select:
SELECT id, name FROM users;
and to get the number of entries:
SELECT COUNT(id) FROM users;
Its becuase you are using an aggregate function in the select part of the query,
to return the 10 records you just need the id, and first_name in the query.
EG:
SELECT id, first_Name
FROM users
if you wanted to get a count of the records in the table then you could use
SELECT (Count(id))
FROM [users]
It's not "wrong", but it is meaningless without a "group by" clause - most databases will reject that query, as aggregate functions should include a group by if you're including other columns.
Not sure exactly what you're trying to achieve with this?
select id, first_name,(select count(*) from users) AS usercount from users;
will give each individual user and the total count but again, not sure why you would want it.
select id, first_name from users,(select count(*) as total from users) as t;
COUNT is an aggregate function and it will always give you count of all records in table unless used in combination with group by.
If you use it in combination with normal query, then it will take priority in deciding the final output as in your case it returns 1.
If you want to return all 10 records, you should just write -
select id,first_name from users
If you need number of rows in a table, you can use MySQL's SQL_CALC_FOUND_ROWS clause. Check MySQL docs to see how it's used.

Will grouping an ordered table always return the first row? MYSQL

I'm writing a query where I group a selection of rows to find the MIN value for one of the columns.
I'd also like to return the other column values associated with the MIN row returned.
e.g
ID QTY PRODUCT TYPE
--------------------
1 2 Orange Fruit
2 4 Banana Fruit
3 3 Apple Fruit
If I GROUP this table by the column 'TYPE' and select the MIN qty, it won't return the corresponding product for the MIN row which in the case above is 'Apple'.
Adding an ORDER BY clause before grouping seems to solve the problem. However, before I go ahead and include this query in my application I'd just like to know whether this method will always return the correct value. Is this the correct approach? I've seen some examples where subqueries are used, however I have also read that this inefficient.
Thanks in advance.
Adding an ORDER BY clause before grouping seems to solve the problem. However, before I go ahead and include this query in my application I'd just like to know whether this method will always return the correct value. Is this the correct approach? I've seen some examples where subqueries are used, however I have also read that this inefficient.
No, this is not the correct approach.
I believe you are talking about a query like this:
SELECT product.*, MIN(qty)
FROM product
GROUP BY
type
ORDER BY
qty
What you are doing here is using MySQL's extension that allows you to select unaggregated/ungrouped columns in a GROUP BY query.
This is mostly used in the queries containing both a JOIN and a GROUP BY on a PRIMARY KEY, like this:
SELECT order.id, order.customer, SUM(price)
FROM order
JOIN orderline
ON orderline.order_id = order.id
GROUP BY
order.id
Here, order.customer is neither grouped nor aggregated, but since you are grouping on order.id, it is guaranteed to have the same value within each group.
In your case, all values of qty have different values within the group.
It is not guaranteed from which record within the group the engine will take the value.
You should do this:
SELECT p.*
FROM (
SELECT DISTINCT type
FROM product p
) pd
JOIN p
ON p.id =
(
SELECT pi.id
FROM product pi
WHERE pi.type = pd.type
ORDER BY
type, qty, id
LIMIT 1
)
If you create an index on product (type, qty, id), this query will work fast.
It's difficult to follow you properly without an example of the query you try.
From your comments I guess you query something like,
SELECT ID, COUNT(*) AS QTY, PRODUCT_TYPE
FROM PRODUCTS
GROUP BY PRODUCT_TYPE
ORDER BY COUNT(*) DESC;
My advice, you group by concept (in this case PRODUCT_TYPE) and you order by the times it appears count(*). The query above would do what you want.
The sub-queries are mostly for sorting or dismissing rows that are not interested.
The MIN you look is not exactly a MIN, it is an occurrence and you want to see first the one who gives less occurrences (meaning appears less times, I guess).
Cheers,