Let's say I have a table that lists cars by user.
id | user_id | color
1 | 1 | red
2 | 1 | red
3 | 2 | blue
4 | 2 | red
5 | 3 | red
Now, I want to know how much red cars each client has, so I've done this SQL :
SELECT user_id, COUNT(color)
FROM cars
WHERE color = 'red'
GROUP BY user_id
Which lists me :
1 | 2
2 | 1
3 | 1
But what I really want is the count of each count. Something like :
Users with 1 red car : 2
Users with 2 red car : 1
...
So is there a way to count my select which already includes a count() grouped by ?
Thank you in advance !
Use an aggregation of aggregations:
SELECT redCount, COUNT(*)
FROM (SELECT user_id, COUNT(color) as redCount
FROM cars
WHERE color = 'red'
GROUP BY user_id
) uc
GROUP BY redCount;
Related
I'm having problem to get the right result from the following tables
table_buyer
pkey | buyer_id | buyer_name
1 | 1 | john
2 | 2 | mike
table_fruit
pkey | buyer_id | fruit_name
1 | 1 | banana
2 | 1 | banana
3 | 1 | apple
4 | 2 | grape
5 | 2 | grape
6 | 2 | grape
then i'm trying to run the following query
select buyer_name, (select count(*) from (select fruit_name from table_fruit where buyer_id = table_buyer.buyer_id group by fruit_name) as table_group_of_fruit) as group_of_fruit from table_buyer;
expected result
buyer_name | group_of_fruit
john | 2
mike | 1
error message : Unknown column 'table_buyer.buyer_id' in 'where clause'
and count(*) does not count grouped fruit as a group but individually.
It seems simple and easy but i've been thinking about this for 2 days and still don't have a clue to get the right result as expected, any help will be greatly appreciated
I think you want to aggregate by buyer and then select the distinct count of fruit:
SELECT b.buyer_name, COUNT(DISTINCT f.fruit_name) AS group_of_fruit
FROM table_buyer b
LEFT JOIN table_fruit f
ON f.buyer_id = b.buyer_id
GROUP BY b.buyer_name;
Note that if two or more buyers could share the same name, you might want to also add the buyer_id to the select and group by clauses:
SELECT b.buyer_id, b.buyer_name, COUNT(DISTINCT f.fruit_name) AS group_of_fruit
FROM table_buyer b
LEFT JOIN table_fruit f
ON f.buyer_id = b.buyer_id
GROUP BY b.buyer_id, b.buyer_name;
I'm sure I'm not the first to need to do this, but I couldn't find a similar question that accounted for the nuance.
I have 3 tables (fav_food, fav_color, and fav_place) that all follow a similar pattern:
userid | label | rank |
=================================
1 | red | 1
1 | green | 2
1 | orange | 3
2 | blue | 1
2 | red | 2
...
Each table will have at most 3 items per userid, but some users might have fewer than 3, and other users might have none for a given table. i.e., it's possible user 10 has 2 favorite colors, 1 favorite food, and 0 favorite places.
I'm looking for a query that can output my data like so:
userid | fav_food | fav_place | fav_color | rank
===========================================================
1 | pizza | New York | red | 1
1 | burgers | NULL | green | 2
1 | NULL | NULL | orange | 3
2 | tacos | Chicago | blue | 1
2 | burgers | Orlando | red | 2
...
Basically, all ranked 1 items together, ranked 2 items together, and ranked 3 items together (NULLs were no item of that rank exists).
I was able to get it working using 3 separate queries (one for each table) + post processing at the application layer, but for the sake of my personal knowledge base, I was wondering if anyone knew how to do it in a single query.
Many thanks!
#Isick,
You can do this with a LEFT OUTER JOIN on each table to a table containing just the userid and rank. DEMO
select user_rank.userid, user_rank.rank, f.food, p.place, c.color from
(
select userid, rank from fav_food
union
select userid, rank from fav_place
union
select userid, rank from fav_color
) user_rank
left outer join
( select userid, rank, label as food from fav_food) f
on user_rank.userid = f.userid and user_rank.rank = f.rank
left outer join
( select userid, rank, label as place from fav_place) p
on user_rank.userid = p.userid and user_rank.rank = p.rank
left outer join
( select userid, rank, label as color from fav_color) c
on user_rank.userid = c.userid and user_rank.rank = c.rank
order by userid, rank
I have 2 tables, 'item' and 'propvalues', propvalues have property_id and value column, what im trying to get is to group propvalues as property_id, and count how many similar values they have.
i know it is similar to another question, but i was unable to figure out how to change it for myself to work. if someone is good at mysql please dont mark it as a duplicate question, but rather try to give me at least some advice. i dont understand what is going on when there is an inner select statement
Here are the tables:
'item'
id category_id
1 1
2 1
3 2
4 5
etc.
'propvalues'
id item_id property_id value
1 1 3 'blue'
2 1 3 'blue'
3 1 3 'blue'
4 1 3 'red'
5 1 5 'blue'
6 1 5 'red'
7 2 5 'red'
SELECT propvalues.property_id,
GROUP_CONCAT(propvalues.value)
FROM propvalues JOIN item ON item.id = propvalues.item_id
WHERE item.category_id = 1 || item.category_id = 2
GROUP BY propvalues.property_id
this give this result:
property_id value
3 blue,blue,blue,red
5 blue,red,red
but i need this, result, i want only the unique values,and count them:
3 blue,3|red,1
5 blue,1|red,2
any ideas ?
i found some solution here: mysql group_concat with a count inside?
but im unable to figure out how to change it for myself to work.
Derived from the refered duplicate:
SELECT property_id, GROUP_CONCAT(CONCAT(value, ',', cnt) SEPARATOR '|')
FROM (
SELECT property_id, value, COUNT(value) AS cnt
FROM propvalues
JOIN item ON item.id = propvalues.item_id
AND item.category_id IN (1, 2)
GROUP BY property_id, value
) t
GROUP BY property_id
To break it down, the inner subquery fetches a number of distinct values per property_id:
+-------------+-------+-----+
| property_id | value | cnt |
+-------------+-------+-----+
| 3 | blue | 3 |
| 3 | red | 1 |
| 5 | blue | 1 |
| 5 | red | 2 |
+-------------+-------+-----+
The outer main query further aggregates theses values by distinct property_id, concatenates value and count to a string (CONCAT(value, ',', cnt)) and then concatenates those from each row (GROUP_CONCAT(... SEPARATOR '|')).
Based on these two tables:
products
| ID | Active | Name | No
--------------------------------------------------
| 1 | 1 | Shirt | 100
| 2 | 0 | Pullover | 200
variants
| MasterID | Active | Name | No
--------------------------------------------------
| 1 | 1 | Red | 101
| 1 | 0 | Yellow | 102
I want to get every product which is active and also their active variants in one sql.
Relation between those tables MasterID -> ID
Needed result:
ID (master) | Name | No
--------------------------------------------------
1 | Shirt | 100
1 | Red | 101
I tried it with using union, but then I am not able to get the belonging MasterIDs.
It looks like you just need a simple join:
select *
from products
left join variants
on products.ID = variants.MasterID
where products.Active = 1
and variants.Active = 1
Update after requirements were made clearer:
select ID, Name, No, 'products' as RowType
from products
where Active = 1
union
select variants.MasterID as ID, variants.Name, variants.No, 'variants' as RowType
from products
join variants
on products.ID = variants.MasterID
where products.Active = 1
and variants.Active = 1
order by ID, RowType, No
I've assumed you want the results ordered by ID, with products followed by variants. The No column may order it this way implicitly (it's impossible to know without real data), in which case the RowType column can be removed. The order by clause might need to be altered to match your specific RDBMS.
This should gives you the expected result:
select * from products left join variants on products.id = variants.masterId
where products.active=1 and variants.active=1
If not please add the expected result to your question.
I want to achieve this table:
|Country|Cars|Blue Cars|Red Cars| Green Cars |
|Mexico | 22 | 12 | 8 | 2 |
|U.S.A | 12 | 6 | 3 | 3 |
|Denmark| 10 | 3 | 2 | 5 |
That from a database table that makes a report (row) for every car, like this:
|Country|car_color|
|Mexico | Blue |
|U.S.A | Red |
|Denmark| Blue |
|Denmark| Blue |
|Mexico | Blue |
|Denmark| Green |
|Denmark| Red |
|U.S.A | Red |
|Denmark| Green |
I did the first part: grouping the countries and get the total number of cars by country, that was with this query:
SELECT country,
COUNT(county)
FROM my_table
GROUP BY country
ORDER BY COUNT(country)
My question is, how do I get the color car columns in the first table after grouping the rows by county and getting the total number of cars by every country?
Note: I tried several ways but I'm failing to achieve this. As an example, I used:
SELECT country,
COUNT(country),
COUNT(case when car_color = 'Green' then 1 else 0 end)
FROM my_table
GROUP BY country
ORDER BY COUNT(country)
But that only shows the same value of Cars (total number of cars in a country) for the column "Green Car".
Help please!
COUNT counts non-NULL rows and your CASE always returns a value.
Either switch to SUM or omit the ELSE part:
SELECT country
,COUNT(*) AS cars
,SUM(case when car_color = "blue" then 1 else 0 end) AS "blue cars"
,SUM(case when car_color = "red" then 1 else 0 end) AS "red cars"
,COUNT(case when car_color = "green" then 1 end) AS "green cars"
FROM my_table
GROUP BY country
ORDER BY COUNT(*) DESC