How to select values by the count of a filed? - mysql

How to select values in MySQL table by the count of a field in the same table ?
Example:
Table users has id, name, password, country
I want to select all ids of only top 3 countries with highest users count to look like this:
country, id
When I try this
WHERE country IN (SELECT country FROM USERS GROUP BY country ORDER BY COUNT(id) DESC LIMIT 3)
I get This version of MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery'
Server version: 5.6.33-79.0 Percona Server

Join with a subquery that gets the top 3 countries.
SELECT u.country, u.id
FROM users AS u
JOIN (SELECT country
FROM users
GROUP BY country
ORDER BY COUNT(*) DESC
LIMIT 3) AS u1
ON u.country = u1.country
Practically any use of WHERE column IN (SELECT ...) can be changed to a JOIN like this, and in many cases the performance is better.

How to select values in MySQL table by the count of a field in the
same table?
Use the GROUP BY field HAVING COUNT(*)=123 aggregation expression after the WHERE clause if there is.

Try this:
SELECT country, id
FROM
(
SELECT country,count(Id) as [NumberofUsers]
FROM USERS
GROUP BY country
) X
INNER JOIN USERS U ON X.Country=U.Country
ORDER BY X.[NumberofUsers] DESC LIMIT 3

Related

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

mysql query select * from table where image!='' order by date and with different upload user

I want to make some mysql query, query out 5 image order by date, but from 5 different upload user.
mysql datatable Structure: id, user_id, image, text, date
SELECT *
FROM mytable
WHERE image!=''
GROUP BY user_id
ORDER BY date DESC
LIMIT 5
But this GROUP BY always cause get the user_id earlier upload image then make a ORDER BY date DESC, I need the fresh 5 images which uploaded by 5 differents users. Maybe should use some UNION, ask for a help, thanks.
Use INNER JOIN with MAX
SELECT
mytable.*
FROM
mytable
INNER JOIN
(SELECT MAX(id) AS ID, id FROM mytable GROUP BY user_id) AS m
ON m.id = mytable.id
WHERE image != ''
GROUP BY user_id
ORDER BY DATE DESC
LIMIT 5
This will fetch the max(latest) id and integrate it to the outer select
Try this query
SELECT *
FROM temp
WHERE image!=''
GROUP BY user_id
HAVING date=max(date)
LIMIT 5
Not sure about mysql but this works in sybase.

can this sql query be simplified?

I have 2 tables. MySql
users : A_ID,name
event : B_ID, A_ID,cat_id,date
Now I want to get all users , who participated more at events on a given period of time, and need to add based on category too. I am doing something like this :
select name from users ,
(select A_id, count(*)
from event
where date<=givendate
group by A_id
order by count(*) desc ) e
where users.A_id=e.a_id
limit 0,5
Is there any easy and prof way to write that script ?
Thanks
Your query looks OK apart from a few minor points:
Your ORDER BY and LIMIT should be in the outer select otherwise the order of the results is indeterminate.
Use the JOIN keyword to join two tables.
Try this:
SELECT u.name
FROM users AS u
JOIN
(
SELECT A_id, COUNT(*) AS cnt
FROM event
WHERE date <= givendate
AND cat_id = 42
GROUP BY A_id
) AS e
USING (A_id)
ORDER BY e.cnt DESC
LIMIT 5

mysql combine two selects?

The first select is
select user_id, count(*) as count
from users
where referrer IS NOT NULL
group by referrer
order by count DESC
Then based off the records returned by that query I need to get the date for the user who referred the users in the above query.
select user_id from users where token = IDS_FROM_LAST_QUERY
I know I could use a sub query and say where IN (subquery) but I'm getting tripped up trying to keep the count from the subquery.
So in the end I need the following info
user_id, count
select o.user_id user_id, count(*) count
from users o
join users i on o.token = i.user_id
where i.referrer is not null
group by referrer
order by count desc
I would use a CTE (common table expression). CTE is super handy to look to get one population and then query the same or slightly different population from the CTE.
WITH Referrer (user_id, count) AS
(
select user_id, count(*) as count
from users
where referrer IS NOT NULL
group by referrer
order by count DESC
)
select
users.user_id
,Referrer.count
from users
inner join Referrer.user_id = users.user_id