mysql slow COUNT() - mysql

I'm having some difficulties with a query:
SELECT d.*,
(SELECT COUNT(id) FROM downloads WHERE category = d.category) AS count
FROM downloads d
GROUP BY d.category
ORDER BY count DESC
So, I'm trying to get the total downloadcount of each category but this query hangs each time I run it.
The downloads table has +- 20000 rows
What am I doing wrong?

SELECT category, count(id) as count
FROM downloads d
GROUP BY d.category
ORDER BY count DESC

I think you'd be better off doing this:
SELECT category, count(*) as cnt
FROM downloads
GROUP BY category
ORDER BY cnt desc;

Related

How to get the current id from an outer query in a nested select

I'm trying to fetch the most common value from a column when I group entries.
I figured I have to use a GROUP BY in order to get that working. I have the following query:
SELECT post_id, (SELECT browser from visits WHERE
id = ? GROUP BY browser ORDER BY count(browser)
DESC limit 1) as common_browser, count(id) as visits FROM `visits` group by post_id
On the "?" I want to pass the ID of the group, it does what I'm trying to do if I pass a parameter to it, i.e: id = 1.
If there's any other way to accomplish this, please let me know!
Use a correlated subquery.
SELECT post_id, (
SELECT browser
FROM visits AS v1
WHERE v1.post_id = v.post_id
GROUP by browser
ORDER BY COUNT(*) DESC
LIMIT 1) AS common_browser, COUNT(*) AS visits,
FROM visits AS v
GROUP BY post_id

how to delete from one table where count less than?

I have 2 tables.
I use this query to find the number of occurences of a field from one table in another table
select t.id, t.tag_text, count(*) cnt from sms s, template as t
where s.id_template=t.id
group by t.tag_text
order by cnt desc
How can I delete all rows from template if they occure in sms less than 5 times for example? Which would mean if count is less than 5. I use MySQL.
delete from template
where id in
(
select id_template
from sms
group by id_template
having count(*) < 5
)
You can use having for filter aggregated result eg:
select t.id, t.tag_text, count(*) cnt
from sms s, template as t
where s.id_template=t.id
group by t.tag_text
having count(*) <5
order by cnt desc
and for delete eg:
delete from
from sms as s
inner join template as t on s.id_template=t.id
group by t.tag_text
having count(*) <5

MySQL - if row is duplicate, return only the first one

I have a MySQL table "results" which has the following fields:
id (PK, AI), user_id (FK), date, score, time
I want to be able to query this table so that it sorts and returns the fields in order of score (descending order) followed by time (ascending order). So something like:
SELECT * FROM results ORDER BY score DESC, time ASC.
However, after this sorting, if more than one row has the same user_id, I only want to include the highest row.
How would I do this?
You can do this with not exists:
SELECT *
FROM results r
WHERE NOT EXISTS (select 1 from results r2 where r2.user_id = r.user_id and r2.id > r.id)
ORDER BY score DESC;
This will work best with an index on results(user_id, id).
My suggestion: SELECT user_id, max(score), time FROM results GROUP BY user_id ORDER BY score DESC;
Select id and highest score per user_id via max() and Group By. Then order the records by score descending.
EDIT: If you need the time for the user-score and there is only one entry with the same score you can use a subselect to get this time:
SELECT user_id, max(score), (
SELECT max(time)
FROM results AS r2
WHERE r2.user_id = r1.user_id
AND r2.score = max(r1.score)
) AS time
FROM results AS r1
GROUP BY user_id
ORDER BY score DESC;
I've managed to get something working at the moment.
SELECT user_id, score, time
FROM results T
WHERE T.score = (
SELECT MAX(T2.score)
FROM results T2
WHERE T2.user_id = T.user_id
)
ORDER BY score DESC, time ASC;

Find the most popular in mysql

My table is
f1(drinker,shop)
The table has a list of drinkers and the shops which they visit.I need to find the most popular shop.I know I can do a simple group by of shops and order it in a descending way and limit the results to 1 but my doubt is what if two or more shop have the same number of drinkers in that case my query fails.I can't use limit 2 or 3 because I want a general working query and not a one specific to the data.I am running out of ideas.
Note:
Please don't show this way:
select shop from f1 group by shop order by count(*) desc limit 1
In that case, you have to compare the counts. Not so pretty with a group by query:
select shop
from f1
group by shop
having count(*) = (select max(cnt)
from (select count(*) as cnt
from f1
group by shop
) s
);
You could also do this as a subquery:
select shop
from f1 join
(select count(*) as cnt
from f1
group by shop
order by count(*) desc
limit 1
) f1max
group by shop
having count(*) = max(f1max.cnt);

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.