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
Related
Actually I'm working with the following table fsa_areas:
Note that each area has a responsible
Now, what I need to do, is to order the same table as following:
Note that now the results are ordered by the the responsible with more areas and at the end the responsible with less areas.
Is there a way to order them in that way?
You can use a COUNT subquery in the ORDER BY clause:
select a.*
from fsa_areas a
order by (select count(*) from fsa_areas a1 where a1.Responsible = a.Responsible) desc
Another way is to get the count in a derived table and join the base table to it
select a.*
from (
select Responsible, count(*) as cnt
from fsa_areas
group by Responsible
) r
join fsa_areas a using(Responsible)
order by r.cnt desc
In MySQL 8 you can use COUNT() as window function:
select *, count(*) over (partition by Responsible) as cnt
from fsa_areas
order by cnt desc
I have a MySQL table where I have a certain id as a foreign key coming from another table. This id is not unique to this table so I can have many records holding the same id.
I need to find out which ids are seen the least amount of times in this table and pull up a list containing them.
For example, if I have 5 records with id=1, 3 records with id=2 and 3 records with id=3, I want to pull up only ids 2 & 3. However, the data in the table changes quite often so I don't know what that minimum value is going to be at any given moment. The task is quite trivial if I use two queries but I'm trying to do it with just one. Here's what I have:
SELECT id
FROM table
GROUP BY id
HAVING COUNT(*) = MIN(SELECT COUNT(*) FROM table GROUP BY id)
If I substitute COUNT(*) = 3, then the results come up but using the query above gives me an error that MIN is not used properly. Any tips?
I would try with:
SELECT id
FROM table
GROUP BY id
HAVING COUNT(*) = (SELECT COUNT(*) FROM table GROUP BY id ORDER BY COUNT(*) LIMIT 1);
This gets the minimum selecting the first row from the set of counts in ascendent order.
You need a double select in the having clause:
SELECT id
FROM table
GROUP BY id
HAVING COUNT(*) = (SELECT MIN(cnt) FROM (SELECT COUNT(*) as cnt FROM table GROUP BY id) t);
The MIN() aggregate function is suposed to take a column, not a query. So, I see two ways to solve this:
To properly write the subquery, or
To use temp variables
First alternative:
select id
from yourTable
group by id
having count(id) = (
select min(c) from (
select count(*) as c from yourTable group by id
) as a
)
Second alternative:
set #minCount = (
select min(c) from (
select count(*) as c from yourTable group by id
) as a
);
select id
from yourTable
group by id
having count(*) = #minCount;
You need to GROUP BY to produce a set of grouped values and additional select to get the MIN value from that group, only then you can match it against having
SELECT * FROM table GROUP BY id
HAVING COUNT(*) =
(SELECT MIN(X.CNT) AS M FROM(SELECT COUNT(*) CNT FROM table GROUP BY id) AS X)
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);
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
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