SQL order by count in an optimal way - mysql

When we have to print the count of a table while doing order by the count itself, is the below query optimal-
SELECT Group, COUNT( * )
FROM table
GROUP BY Group
ORDER BY COUNT( * ) DESC
I am thinking that the order by count(*) would do a count and then the select would also do the count. Does MySQL optimize this query so that count is done only once?
I was looking at SQL Order By Count when I thought if there was a better solution possible.

Related

MySQL Row more appear with multiple row same result

I have a query with a count with some group by, and I want to get the greater count. I can do with an order by and limit 1, but I have multiple results with the same count and then does not work for me.
How do I solve this problem?
With MySql 8+, you can use CTE to get the maximum count, and then retrieve all records with a count equal to the maximum count.
However, since CTE is not available in MySql 5.6, you'd need to use a sub-query to get the maximum count, and then write the main query which compares the count of each record to the maximum count retrieved in the subquery.
Here is a query I wrote. Maybe it's not the most efficient solution, but it gets the desired result.
SELECT
group_id, COUNT(record_id) c
FROM
table_name
GROUP BY group_id
HAVING c IN (
SELECT
MAX(sub_query.c)
FROM
(SELECT
group_id, COUNT(record_id) c
FROM
table_name
GROUP BY group_id) AS sub_query
)
If you are not going to do this using window functions, you can do:
SELECT group_id, COUNT(*) as cnt
FROM table_name
GROUP BY group_id
HAVING cnt = (SELECT COUNT(*)
FROM table_name
GROUP BY group_id
ORDER BY COUNT(*) DESC
LIMIT 1
) ;

How to get the total records details along with the query which is having a limit

How to get the total records details along with the query which is having a limit
My MySQL query is given below
SELECT name FROM employees LIMIT 10
which will give me 10 rows, but the total records will be around 6000. How can we get that also along with the above query
Use a subquery:
SELECT name, (SELECT COUNT(*) FROM employees) AS cnt
FROM employees
LIMIT 10
Use a Sub-query
SELECT nameFROM,
(select count(1) from employees) as total_count
From employees
LIMIT 10
or CROSS JOIN
SELECT nameFROM,total_count
From employees
CROSS JOIN (select count(1) total_count from employees) A
LIMIT 10
Adding ORDER BY to your query will make the result consistent
You can use SQL_CALC_FOUND_ROWS option in your query which will tell MySQL to count total number of rows disregarding LIMIT clause. You still need to execute a second query in order to retrieve row count, but it’s a simple query and not as complex as your query which retrieved the data. Usage is pretty simple. In you main query you need to add SQL_CALC_FOUND_ROWS option just after SELECT and in second query you need to use FOUND_ROWS() function to get total number of rows
SELECT SQL_CALC_FOUND_ROWS name FROM employees WHERE LIMIT 10
SELECT FOUND_ROWS();
(SELECT NAME, 1 AS 'Obs' FROM employees LIMIT 10)
union select 'RecsinTable', count(*) from employees

Count of total rows which have duplicates

I'm trying to get a total count of all the rows in a table which have duplicates.
Here is the query I am using right now:
SELECT count( `id_lead` )
FROM `lead_history`
GROUP BY `id_lead`
HAVING count( * ) > 1
The problem is that this isn't counting the total number of rows, it is counting the total amount of times each row contains a duplicate and returning that.
So right now, it is returning like this:
2
4
6
2
Given those results, I actually want my query to return 4, since there are 4 rows which have duplicates. The amount of duplicates each row has does not matter to me.
How would I write this query without using subqueries?
If you were using something like Oracle or SQL Server, you could take advantage of analytic functions. But MySQL does not have these, so using a subquery might the best way to get your answer.
SELECT COUNT(*)
FROM `lead_history`
WHERE `id_lead` IN (SELECT `id_lead` FROM `lead_history` GROUP BY `id_lead` HAVING COUNT(*) > 1)
Note that the subquery is not correlated, so the query optimizer should be able to make this run reasonably efficiently.
Try this way
SELECT COUNT(*)
FROM `lead_history` as b
join (SELECT `id_lead` FROM `lead_history` GROUP BY `id_lead` HAVING COUNT(*) > 1) a on b.id_lead=a.id_lead
Try This
SELECT count( * )
FROM `lead_history`
GROUP BY `id_lead`
HAVING count( * ) > 1
You're almost there, just put your query in a derived table and select the count from that. No additional in or join needed:
select count(*) from (
select `id_lead`
from `lead_history`
group by `id_lead`
having count(*) > 1
) t

MySQL select SUM with LIMIT AND WHERE

I'm trying to select the SUM of a few values with a limit of 2. I've seen a couple of example of this (9877872) but have been unable to get it working. I have
SELECT SUM(points)
FROM
(SELECT points FROM user_table
WHERE city=1 AND group =5)
AS min_points ORDER BY points DESC LIMIT 2
However the limit clause at the end of the query does not seem to be executed and I just get the sum of all the users in the table...
Would anyone know what I'm doing wrong...?
Try this
SELECT SUM(points)
FROM
(SELECT points FROM user_table
WHERE city=1 AND group =5 ORDER BY points DESC LIMIT 2) AS t1

MySQL - using GROUP BY and DESC

In my SQL query I am selecting data with GROUP BY and ORDER BY clauses. The table has the same numbers across multiple rows with different times in each row. So I think I want to apply a GROUP BY clause.
However in the results return the oldest time with the number, but I need the most recent time.
SELECT * FROM TABLE GROUP BY (numbers) ORDER BY time DESC
The query appears as if it should first apply GROUP BY and then ORDER BY... but the results do not appear to work this way.
Is there any way to fix this?
SELECT *
FROM table t
WHERE time = (
SELECT max(time)
FROM table
WHERE t.numbers = numbers
)
work-around is to re-write the query as:
SELECT * FROM (SELECT * FROM table ORDER BY time DESC) AS t GROUP BY numbers;
SELECT * FROM table
WHERE time IN (
SELECT MAX(time)
FROM table
GROUP BY numbers
)
According to the manual you can add desc to the group by list:
Example:
group by item1, item2 desc, item3
with or without rollup.
I've tried this and it works in Ubuntu version 5.5.58. The reference page is:
https://dev.mysql.com/doc/refman/5.7/en/group-by-modifiers.html
SELECT * FROM TABLE GROUP BY numbers DESC;
This will give you last record from group.
Thanks