MySQL - SELECT Most occuring value (with several same occurrences) - mysql

I have been looking for a way to do a MySQL select to get all the most occuring values. All the solutions i have found where with using LIMIT 1, but this doesn't help if there are more than one value that occur the same amount of times. E.g:
customer
ID
FirstName
1
Bob
2
Tom
3
Bob
4
Robert
5
Tom
6
Timothy
The Select for most occuring FirstNames should result in:
FirstName
Bob
Tom
Since both occur twice.
I have tried the following:
SELECT FirstName FROM (
SELECT FirstName, COUNT(FirstName) as counter FROM customer
GROUP BY FirstName
HAVING counter = MAX(counter)
) s
But this doesn't seem to work, i would really appreciate a nudge in the right direction.

There can be different ways for doing this
you can try
1st
SELECT FIRSTNAME
FROM customer
GROUP BY FirstName Having count(FirstName) = (
SELECT COUNT(FirstName) FROM customer GROUP BY FirstName ORDER BY 1
DESC LIMIT 1);
2nd
with cte as
(
SELECT COUNT(FirstName) MaxCounter
FROM customer
Group By FirstName ORDER BY COUNT(FirstName) DESC LIMIT 1
)
SELECT c.FirstName
From customer c
Group BY FirstName
HAVING COUNT(FirstName) = (SELECT MaxCounter FROM cte)

Related

How to get other row value while grouping query?

Let me explain with example,
id firstname lastname Mark
--------------------------------
1 arun prasanth 40
2 ann antony 45
3 sruthy abc 41
6 new abc 47
1 arun prasanth 45
1 arun prasanth 49
2 ann antony 49
and AS IS, if I query like:
select count(*) as count, firstname, lastname, Mark
from tableA
group by id
order by count desc
then in the result, 3 arun ~~ row will be on the top. I have to keep this order(count desc)
But I want to search each Mark score which are 49 45 40.
I want to put result in $sql and use it like $sql['(every mark score for ann)'], how do I do that?
Use GROUP_CONCAT:
SELECT COUNT(*) AS COUNT, firstname, lastname, GROUP_CONCAT(mark) AS Mark
FROM tableA
GROUP BY id
ORDER BY COUNT DESC
This will show mark like '40, 45, 49' with comma. If you don't want comma, add SEPARATOR in the GROUP_CONCAT like below:
SELECT COUNT(*) AS COUNT, firstname, lastname, GROUP_CONCAT(mark SEPARATOR ' ') AS Mark
FROM tableA
GROUP BY id
ORDER BY COUNT DESC
This will use a space(' ') as separator instead of comma like '40 45 49'. Of course you can define any separator you want.
Use Having clause on your query for result
select count(*) as count, firstname, lastname, Mark
from tableA
group by id having by firstname = 'ann'
order by count desc
If you want the original data, use count() or a subquery in the order by:
select a.*
from tableA a
order by count(*) over (partition by id) desc,
id
In older versions of MySQL, you can use a subquery instead:
select a.*
from tableA a
order by (select count(*) from tableA a2 where a2.id = a.id) desc,
id

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 |

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]

Is it possible to do a group by count(distinct) without a join?

Table 1 : (Company)
ID Name
1 A
2 B
3 C
Each company (pk = ID) can have one or more employees.
Table 2 : (Employee) (CompanyID referencing ID)
CompanyID EmpID Name
1 1 Joe
1 2 Doe
1 3 Boe
2 4 Lou
3 5 Su
3 6 Ram
Query :
select CompanyID, count(*) from Employee group by CompanyID having count(*) > 1; # Lists companies and their counts.
CompanyID count(*)
1 3
3 2
For this query, I want just one result with the count of distinct CompanyIDs. So, '2' in this case [Companies A and C].
In short, I am looking for number of companies with 2 or more employees.
Is there anyway to get the result without a temp table or a join? I am using MySQL.
Yes:
select count(*) from
(select CompanyID from Employee group by CompanyID having count(*) > 1) v
or for ranges:
select count(*) from
(select CompanyID from Employee group by CompanyID
having count(*) >= 5 and count(*) < 10) v
Yes, it's possible with subqueries:
SELECT COUNT(*)
FROM
( SELECT 1
FROM Employee
GROUP BY CompanyID
HAVING COUNT(*) > 1
) AS grp
or:
SELECT COUNT(DISTINCT CompanyID)
FROM Employee AS e
WHERE EXISTS
( SELECT *
FROM Employee AS e2
WHERE e2.CompanyID = e.CompanyId
AND e2.EmpID <> e.EmpID
)
or perhaps if COUNT(*) is slow, you can use MIN() and MAX():
SELECT COUNT(*)
FROM
( SELECT 1
FROM Employee
GROUP BY CompanyID
HAVING MAX(EmpID) > MIN(EmpId)
) AS grp

MySQL row number

Say I have a MySQL query, for example:
SELECT id, name, surname FROM employees ORDER BY id
The result woud be:
id name surname
1 Peter Smith
2 John Banjo
...
1384 Will Levenstein
While this is an ordered query, I can always assume (as long as I don't change the table) that John Banjo will come out second.
Now what if my query was
SELECT id, name, surname FROM employees WHERE name = 'John' AND surname = 'Banjo'
Could I somehow get what the row number would be in the first query?
I'm trying to do this in a much more complicated, but always ordered query, is there any way to archieve this?
SELECT x.id, x.name, x.surname, x.rownum
FROM (
SELECT #rownum:=#rownum+1 rownum, t.*
FROM (SELECT #rownum:=0) r, employees t
ORDER BY Id
) x
WHERE x.name = 'John'
AND x.surname = 'Banjo'