Selecting the top row in each group in mysql - mysql

I have a table with two columns - region and profession
region | profession
India | IT
India | IT
US | HR
US | HR
India | HR
I want to display the most popular profession in every region. the output should only be
Region | Profession
India | IT
US | HR

First, get a count of the results per group. Then you need to establish an order per group -- mysql can do this with user-defined variables.
Here's an example:
select region, profession
from (
select region, profession,
#rn:=if(#oldregion=region,#rn+1,0) rn,
#oldregion:=region
from (
select region, profession, count(*) cnt
from yourtable
group by region, profession) t, (select #rn:=0, #oldregion='') t2
order by region, cnt desc) t3
where rn = 0
SQL Fiddle Demo
Here's another solution using a correlated subquery:
select distinct region, (
select profession
from yourtable t2
where t.region = t2.region
group by region, profession
order by count(*) desc
limit 1) as profession
from yourtable t
More Fiddle

Related

SQL Query to find records belongs to two states

cust_id
state
1
CA
2
IL
3
SC
1
PA
3
IA
4
MO
5
VA
4
NY
Can any one please advise on SQL Query that return the cust_id that belong to two states as below:
The output should be
cust_id
state
1
CA
1
PA
3
SC
3
IA
4
NY
4
MO
Try the following query
Solution 1
Select * From yourtable
Where Cust_Id In (Select cust_id From yourtable Group By cust_id Having
Count(*) = 2) Order By cust_id,state
Solution 2
With T1 As
(Select cust_id From yourtable Group By cust_id Having Count(*) = 2)
Select T2.* From yourtable T2 Join T1 On T1.cust_id = T2.cust_id O
Order By T2.cust_id,T2.state
SELECT tmp.*
FROM tmp
INNER JOIN (
SELECT cust_id
,COUNT(STATE) s_count
FROM tmp
GROUP BY [cust_id]
) sub
ON tmp.cust_id = sub.cust_id
WHERE sub.s_count = 2
ORDER BY cust_id
,STATE
One simple approach would use a COUNT window function, that will assign the amount of times each "cust_id" occurs in your table. Once you get this value, you can filter out rows whose count is smaller than 2.
WITH cte AS (
SELECT *, COUNT(cust_id) OVER(PARTITION BY cust_id) AS cnt
FROM tab
)
SELECT cust_id,
state
FROM cte
WHERE cnt > 1
Check the demo here.

Count repeated value from a column for each row with same value in mysql

+------+-------+
| name | value |
+======+=======+
| 5 | 0 |
+------+-------+
| 4 | 0 |
+------+-------+
| 3 | 1 |
+------+-------+
| 4 | 1 |
+------+-------+
| 4 | 1 |
+------+-------+
| 5 | 0 |
+------+-------+
I want to obtain the most repeated value for each name in part.
name 5 have the most repeated value 0
name 4 have the most repeated value 1
name 3 have the most repeated value 1
How can i do that in a single query to mysql ?
Thanks
SOLVED
With the select statement from #nvidot and another posts from SO, i found this is a common problem with this type of query.
Newer versions of MySQL come with ONLY_FULL_GROUP_BY enabled by default, and many of the solutions here will fail in testing with this condition.
So the working formula for me was:
SELECT DISTINCT t1.name, MAX(t1.occ), MAX(t2.value)
FROM (select name, value, count(*) as occ from `table` group by name, value order by occ desc) AS t1
JOIN (select name, adstatus, count(*) as occ from `table` group by name, value order by occ desc) AS t2 ON t2.name = t1.name AND t2.occ = (
SELECT MAX(occ) FROM (select name, value, count(*) as occ from `table` group by name, value order by occ desc) t3 WHERE t3.name = t1.name
)
GROUP BY t1.name;
In Oracle's PL/Sql, there is a specific feature can satisfy your request which is called Window function, but in MySql, there is no such thing untile mysql-8.0
SELECT `column`,
COUNT(`column`) AS `value_occurrence`
FROM `my_table`
GROUP BY `column`
ORDER BY `value_occurrence` DESC
Also please visit this link to more clear.
select name, val
from (select name, val, max(occ)
from (select name, val, count(*) as occ
from `sample` group by name, val
order by occ desc) as groups
group by name) as maximums;
Outer most select serves as cosmetic to display only name and val
order by occ desc serves to obtain the correct val
The following might be sufficient:
select name, val
from (select name, val, count(*) as occ
from `sample`
group by name, val
order by occ desc) as groups
group by name;
[edit]: The following should not trigger error as it does not use non-aggregate column and it does not rely on order by. Multiple name rows might exists if there exists multiples maxs for name/val count.
select name,val
from (select name as maxname, max(occ) as maxocc
from (select name, val, count(*) as occ
from `sample`
group by name, val) as counts2
group by name) as maxs
join (select name, val, count(*) as numocc
from `sample`
group by name, val) as counts1
on name = maxname AND numocc = maxocc;

mysql: union re-use subquery

There is a table:
ID City
1 Toronto
2 Toronto
3 Toronto
4 Toronto
5 NY
6 NY
How to get the following table:
City Total
NULL 6
Toronto 4
NY 2
I plan to use union:
(select city, count(*) as total from tbl group by city)
union
(select null, count(*) as total from tbl)
Is it possible to use something like to reuse the subquery:
(select city, count(*) as total from tbl group by city) tmp
union
(select null, count(*) as tmp from tbl)
Or sql already optimizes
(select city, count(*) as total from tbl group by city)
union
(select null, count(*) as total from tbl)
?
In at least MySQL 5.5 and newer, you can use the WITH ROLLUP modifier to get a total sum of the grouped elements without an extra query;
SELECT city, COUNT(*) AS total FROM tbl GROUP BY city WITH ROLLUP
city total
---------------
NY 2
Toronto 4
(null) 6
An SQLfiddle to test with.
You can't reuse the the query but you could use a view for reuse the code
create view my_view as
select city, count(*) as total
from tbl group by city
once created the view you could
select city, total
from my_view
union
select null, sum(total)
from my_view
1) Take aliases are only visible to join members and subquery. Not to union members.
2) The query as you wrote it makes little sense: aliasing tmp to a table then a scalar?
To achieve what you want to achieve, you can try using CTEs:
WITH tmp AS (SELECT city, COUNT(*) AS cnt GROUP BY city)
SELECT * FROM tmp UNION SELECT null, SUM(cnt) FROM tmp
I don't know what the performance difference would be. If you have an index on city, I doubt you will see a difference.
You use WITH ROLLUP in a subquery and then arrange the ordering in the outer query to put the rollup record on top:
SELECT *
FROM (SELECT city, COUNT(*) AS total FROM mytable GROUP BY city WITH ROLLUP) x
ORDER BY
CASE WHEN city IS NULL THEN 0 ELSE 1 END,
city
If you are planning to order the results by descending total, that's even simpler:
SELECT *
FROM (SELECT city, COUNT(*) AS total FROM mytable GROUP BY city WITH ROLLUP) x
ORDER BY total DESC
Demo on DB Fiddlde:
| city | total |
| ------- | ----- |
| | 6 |
| Toronto | 4 |
| NY | 2 |

Mysql: which pizza prefer client

I have table with this data :
1. John | seafood pizza
2. Mike | pepperoni pizza
3. Mike | pepperoni pizza
4. John | original pizza
5. Mike | original pizza
6. John | seafood pizza
7. John | pepperoni pizza
....
How can I write a query that give me result such this:
John | seafood pizza
Mike | pepperoni pizza
If client have same quantity for many pizzas, the result may be any pizza's name.
Let's take it step by step
the following query will give you number of times each client ordered each kind of pizza
SELECT name, pizza, COUNT(*) AS cnt
FROM yourTable
GROUP BY name, pizza
So how do we get the most often ordered pizza from that? We must first know, what is the highest number of pizza ordered by each client
SELECT name, MAX(cnt) AS cnt FROM (
SELECT name, pizza, COUNT(*) AS cnt
FROM yourTable
GROUP BY name, pizza
) AS subquery GROUP BY name
then use this number to select actual pizza name
SELECT name, pizza, COUNT(*) AS cnt
FROM yourTable AS t
CROSS JOIN (
SELECT name, MAX(cnt) AS cnt FROM (
SELECT name, pizza, COUNT(*) AS cnt
FROM yourTable
GROUP BY name, pizza
) AS subquery GROUP BY name
) AS sq
USING(name,cnt)
GROUP BY name, pizza
I'd go with grouping the counts by user and pizza then using this as a datasource for a query which finds the groupwise maximum (using the max concat trick). It's not hard:
SELECT user, SUBSTRING(MAX(CONCAT(LPAD(freq, 6, '0'),pizza)),7)
FROM
(SELECT user, pizza, COUNT(*) AS freq
FROM user_likes
GROUP BY user, pizza) ilv
GROUP BY user
Let's have a simple solution :
First of all, we have two columns,name and food.
You can list of favorite customer's food easily :
CREATE TEMPORARY TABLE tbltemp AS (
SELECT name, food, COUNT( * ) c
FROM food
GROUP BY name, food
);
Now we have all of foods by count.
Then you can order it by count descending :
SELECT *
FROM tbltemp
ORDER BY c DESC
Now you have a list that describes your customer's favorite.
UPDATE :
Instead of second query ,replace this one :
SELECT tbl1 . *
FROM (
SELECT name, food, COUNT( * ) c
FROM food
GROUP BY name, food
) AS tbl1, (
SELECT name, food, COUNT( * ) c
FROM food
GROUP BY name, food
) AS tbl2
WHERE tbl1.c = tbl2.c
AND tbl2.name = tbl1.name
AND tbl2.food = tbl1.food
AND tbl1.c = (
SELECT c
FROM tbltemp
ORDER BY c DESC
LIMIT 1 )
This query result is your question goal.

Count how many different countries are in the table

I have a table like this:
ID country
-------------
1 US
2 Japan
3 China
4 US
5 China
How can one query the table, so that it returns how many different countries are in the table (i.e 3)?
The following SQL query will result in counting the number of unique countries in your table.
select count(distinct country)
from YourTable
What you need is to select the amount of unique countries. This is done by selecting all country entries, which are then grouped so there is only one country entry per country name.
SELECT count(country) from countrytable group by country;
This is basically the same as Andomars answer.
you can use this
SELECT country, COUNT( id )
FROM [table_name] GROUP BY country
LIMIT 0 , 30
Output :
country count(id)
---------------------
US 2
Japan 1
china 2
SELECT count(distinct country) from countrytable
select count(distinct country)
from table1
SELECT count( DISTINCT country )
FROM table1 c
WHERE c.item_id = (
SELECT main_id
FROM table2
WHERE main_id = c.item_id )
select count(distinct country)
from [TableName]