How to find most repeating element from a table? - mysql

I have a table tbl_user and I want to find which user_name(s) have the most repeating values in the table. I only want to retrieve those user_id(s).
I also need a separate query to find the count the of duplicate user_name(s) in the table .

First query to find the biggest amount of repeated usernames:
SELECT user_name, COUNT(user_id) AS amount
FROM tbl_user
GROUP BY user_name
ORDER BY amount DESC
And then grab id`s:
# faster way using username from last query
SELECT user_id
FROM tbl_user
WHERE user_name = '$user_name'
# longer way
SELECT user_id
FROM tbl_user
WHERE user_name = (
SELECT user_name
FROM tbl_user
GROUP BY user_name
ORDER BY COUNT(amount) DESC
LIMIT 1
)

To find the count of duplicates:
SELECT count(id) AS num_duplicates FROM tbl_users GROUP BY user_name ORDER BY num_duplicates DESC
To find the user_id's of the most duplicated user_name:
SELECT user_id FROM tbl_user
WHERE username IN ( SELECT user_id
FROM tbl_users
GROUP BY user_name
ORDER BY count(id) DESC LIMIT 0, 1)

SELECT COUNT(*) FROM tbl_user
GROUP BY tbl_user.user_name
Will give you the number of duplicate user_names. You can use a scripting language to select out the highest one if you like, or just look at the list if it's not something you need automated.

If you mean you want to count the occurences of a particular username, something like this may work for you.
select user_name,user_id,count(*) as mycount from tbl_user group by user_name order by mycount desc limit 5
This should get the top 5 entries

You could select the user_names which are duplicated with this SQL:
SELECT COUNT(1) AS duplicates, user_name
FROM tbl_user
GROUP BY user_name
HAVING duplicates > 1
Having done this, you can then use it as a subquery to find out the count of duplicate user_names
SELECT COUNT(1) AS count_of_user_names, SUM(duplicates) AS duplicate_records
FROM (
SELECT COUNT(1) AS duplicates, user_name
FROM tbl_user
GROUP BY user_name
HAVING duplicates > 1
) AS subquery
Or use it to find out the user ids:
SELECT user_id
FROM tbl_user
WHERE user_name IN (
SELECT user_name
FROM tbl_user
GROUP BY user_name
HAVING COUNT(1) > 1
)

Related

How do I select a row with max count doing a group by

I have a table posts with columns (id, user_name, thread_id).
A user can submit multiple posts for a thread. thread to post is one to many.
I need to find out who submitted max posts per thread. So the result would be
Max(Count), user_name, thread_id WHERE there will be only one row per thread_id.
The table is too huge so I wanted to get the query optimized as much as I could.
You can try with the group by and having clauses:
select t.user_name, t.thread_id , count(*) as max_count
from tbl t
group by t.user_name, t.thread_id
having count(*) = ( select count(*) as ttl
from tbl
where thread_id = t.thread_id
group by user_name
order by ttl desc
limit 1 )
select user_name, thread_id, count(*) as max
from tbl t
group by user_name, thread_id
having count(*) = (
select count(*) as cnt /* most posts per user per thread */
from tbl
group by user_name, thread_id
order by cnt desc
limit 1
)
Easy workaround for system that don't have limit is:
select user_name, thread_id, count(*) as max
from tbl t
group by user_name, thread_id
having count(*) = (
select max(cnt) from (
select count(*) as cnt /* most posts per user per thread */
from tbl
group by user_name, thread_id
) m
)
Suppose you have a table posts with fields id, user_name & thread_id.
If you want to query which user has posted the most posts on a specific thread and the total number of his posts from a table, you can achieve that with this MySQL query:
SELECT user_name, thread_id, count(thread_id)
FROM posts WHERE thread_id=1 GROUP BY user_name
ORDER BY count(thread_id) DESC LIMIT 1;
It will return only one row...

Subquery - records are not in ordered form

I have three tables:
user: id, name
keyword: id, name
userkeyword: id, user_id, keyword_id
I want to execute query in following way:
Display those users whose keyword/s are matched with the login user's
keywords. In the order of maximum number of keyword matched user
should display first
e.g : If userA having 4 matched keywords, userB having 8, userC having 1, userD having 6 then the result should be in the order of,
userB
userD
userA
userC
For that I have done with this query (assume login user's id is 1):
select *
from user
where id IN (
select user_id
from userkeywords
where keyword_id IN (
select keyword_id
from userkeywords
where user_id=1)
group by user_id
order by count(keyword_id) desc)
AND id != 1
Here the result is getting perfect but the order is not correct. I have merged two queries in following manner"
select *
from user
where id IN (?)
AND id!=1
+
select user_id
from userkeywords
where keyword_id IN (
select keyword_id
from userkeywords
where user_id=1)
group by user_id
order by count(keyword_id) desc
Second query returns user_id in correct order but when I merged both queries, order was changed (wrong).
Hope I have mentioned my query properly with enough detail.
A subquery returns an unordered set, so the order by in a subquery only matters for its limit clause, if there is any. Any database other than MySQL would give an error message for a purely decorative sort order.
There's no way to sort on a column that only exists in the where clause. You'd have to rewrite the query. One option is to replace your in conditions with joins:
select uk2.name
from userkeywords uk1
join userkeywords uk2
on uk1.keyword_id = uk2.keyword_id
and uk1.user_id <> uk2.user_id
join user u2
on u2.id = uk2.user_id
where uk1.user_id = 1
group by
uk2.name
order by
count(*) desc
This should do it.
select uk.user_id, u.name
from userkeywords uk
left join user u on u.id = uk.user_id
where uk.keyword_id IN (
select keyword_id
from userkeywords
where user_id=1)
group by uk.user_id
order by count(uk.keyword_id) desc) AND uk.user_id != 1
Also, JOIN provides better performance.
I would use an inner join to select the correct rows:
SELECT *
FROM user
INNER JOIN (
SELECT * FROM userkeyword
WHERE keyword_id IN (
SELECT keyword_id
FROM userkeyword
WHERE user_id=1
)
) uk
ON user.id = uk.user_id
GROUP BY u.id
ORDER BY count(*) DESC;

SQL: select all the rows from the two userid's with great number of rows

I would like to get all the rows from the two users with the greatest number of rows, that is, the two users with the greatest activity in a log table.
I have only found next solution: first, get the number of rows for every user, an limit it to 2:
SELECT userid, count(*) AS n_of_rows FROM my_table GROUP BY userid LIMIT 2;
Then, from the source code I'm querying the database (Python for example), query the database to get the rows of each user:
SELECT * FROM my_table where userid = $userid
Is it the best/elegant solution, taking into account SQL language itself and database performance?
Thanks!
I think what you're looking for is something like
select * from my_table where userid in
(select userid from my_table
group by userid
order by count(*) desc
limit 2)
To get the rows and keep the order, use a join with aggregation:
select t.*
from my_table t join
(select userid, count(*) as cnt
from my_table
group by userid
order by count(*) desc
limit 2
) top2
on t.userid = top2.userid
order by top2.cnt desc, userid;
Try this:
SELECT TOP 2 userid, count(*) AS n_of_rows
FROM my_table
GROUP BY userid
ORDER BY count(*) desc

Return COUNT in a request

I have this request :
SELECT id_user
FROM posts
GROUP BY id_user
ORDER BY COUNT(*) DESC
...which will return the id_user, ordered by their number of occurrence in the posts table.
But along with the id_user information, I would like to keep track of the COUNT(*) and store it somewhere, but I have no idea how to do it.
Use:
SELECT id_user,
COUNT(*) AS numPosts
FROM posts
GROUP BY id_user
ORDER BY COUNT(*) DESC
The column alias in the example, numPosts, can then be referenced in whatever you're already using to get the id_user column values.
you can do:
select id_user, count(*) total_count
FROM posts
GROUP BY id_user
ORDER BY COUNT(*) DESC
That way you can still retrieve the user id and the total times it appeared in the table

Count unique users from db

I have the following table structure in my db (MySQL):
id group_id item_id project_id user_id
Users can have multiple entries withing the same project. How do I count unique users withing a particular project (minus project owner id)?
SELECT COUNT(user_id) AS cnt
FROM myTable
WHERE project_id = $myProject
AND user_id != 3
GROUP BY user_id
This looks right but I don't believe I'm getting the right results. Am I missing something?
Select Count(Distinct user_id)
From MyTable
Where project_id = $myProject
And user_id != 3
Add DISTINCT to your COUNT and eliminate the GROUP BY.
SELECT COUNT(DISTINCT user_id) AS cnt
FROM myTable
WHERE project_id = $myProject
AND user_id != 3
You don't need a GROUP BY clause for this.
SELECT COUNT(DISTINCT user_id) AS cnt
FROM myTable
WHERE project_id = $myProject
AND user_id != 3;
If you want to list the member count for each group in the same query, you can GROUP BY project_id:
SELECT COUNT(DISTINCT user_id) AS cnt
FROM myTable
GROUP BY project_id;
By grouping on user_id as you do now, every row in the resultset will contain 1.
Try Distinct?
SELECT DISTINCT COUNT(user_id) AS cnt FROM myTable WHERE project_id = $myProject AND user_id != 3