WHERE HAVING COUNT(*) Very slow query - mysql

I'm trying to run a SQL query which takes 32 sec to complete,
any ideas how to run it faster?
SELECT accounts.*
FROM accounts
WHERE accounts.account_id IN (SELECT map.account_id
FROM map
WHERE map.account_id=accounts.account_id
HAVING COUNT(*)<2)
ORDER BY rand()
LIMIT 1

You could use an inner join to achieve that filtering:
SELECT accounts.*
FROM accounts
INNER JOIN (
SELECT map.account_id
FROM map
GROUP BY map.account_id
HAVING COUNT(*) < 2
) AS m ON accounts.account_id = m.account_id
ORDER BY rand()
limit 1
I'm not sure why you are ordering by rand or limiting the result to 1 but could it be repetitive execution of this overall query is a performance issue?

Try converting In clause to EXISTS clause -
SELECT accounts.*
FROM accounts
WHERE EXISTS (SELECT NULL
FROM map
WHERE map.account_id=accounts.account_id
GROUP BY map.account_id
HAVING COUNT(*) < 2
)
ORDER BY rand()
limit 1

Related

how to group by with order by on somewhat complex mysql query

(SELECT dtable.*, new_apps.top as t1 FROM app_detailsvvv as dtable INNER JOIN new_apps ON
new_apps.trackId=dtable.trackId WHERE (SELECT COUNT(*) AS c FROM compositions as dtablev
WHERE parent='169469' AND trackId=dtable.trackId AND new_apps.top > 0)>0) UNION
(SELECT *, 301 FROM app_detailsvvv as dtable WHERE (SELECT COUNT(*) AS c FROM compositions
as dtablev WHERE parent='169469' AND trackId=dtable.trackId)>0) ORDER BY t1 ASC, trackName
ASC LIMIT 0,12
this query brings me duplicates, how can I group by it by trackId ?
Place trackid as part of your SELECT statement ...
SELECT new_apps.trackId,
..etc...
..
..
GROUP BY 1
Make sure the rest of your SELECT items (including the sub-SQL query) have been aggregated - such as MAX, FIRST, SUM or something that groups them into a single result.

MySql query ordering

Here is my data. I want to take 6 rows, but I want all HeadlineCategoryId's to be unique in my result list. If I select the top 6 I would take 2 rows from HeadlineCategoryID 20 (6,2). Do you have any suggestions about it?
SELECT a.*
FROM tableName a
INNER JOIN
(
SELECT HeadlineCategoryID, MAX(Creation) max_date
FROM TableName
GROUP BY HeadlineCategoryID
) b ON a.HeadlineCategoryID = b.HeadlineCategoryID AND
a.Creation = b.max_date
ORDER BY a.Creation DESC -- << specify here how are you going to sort
LIMIT 6 -- the records you want to get
UPDATE 1
SELECT a.*
FROM tableName a
INNER JOIN
(
SELECT HeadlineCategoryID, MAX(NewsID) max_id
FROM TableName
GROUP BY HeadlineCategoryID
) b ON a.HeadlineCategoryID = b.HeadlineCategoryID AND
a.NewsID = b.max_id
ORDER BY a.Creation DESC -- << specify here how are you going to sort
LIMIT 6 -- the records you want to get
It looks like you want the six most recent records, but unique by HeadlineCategoryId. If so, this will work:
select top 6 NewsId, Creation, HeadlineCategoryId
from (select t.*,
row_number() over (partition by HeadlineCategoryId order by Creation desc) as seqnum
from t
) t
where seqnum = 1
As a note . . . This question originally indicated that it was using SQL Server, not MySQL. The solution in MySQL is not as simple. Here is one method with not exists:
select NewsId, Creation, HeadlineCategoryId
from t
where not exists (select 1
from t t2
where t2.HeadlineCategoryId = t.HeadlineCategoryId and
t2.id < t.id)
limit 6
The not exists portion is saying "where there is no other record with a larger id for a given headline category".

most occuring show in mysql table

I have the following data set.
How would the query look if wanted the most occuring show on top and limit the result for 20 shows?
EDIT
I have searched on the web for this and i need to use the GROUP BY method from sql. but when i make the query
SELECT `show` FROM fans GROUP BY `show` LIMIT 20
i do not get the desired result.
SELECT a.*, b.TotalCount
FROM TableName a
INNER JOIN
(
SELECT c.show, COUNT(*) totalCount
FROM TableName c
GROUP BY c.show
) b ON a.show = b.show
ORDER BY b.TotalCount DESC
LIMIT 20
if you want to list one record for every show, you can simply use GROUP BY
SELECT a.show, COUNT(*) TotalCount
FROM TableName a
GROUP BY a.Show
ORDER BY TotalCount DESC
LIMIT 20

sql pulling from sub query

Is it possible to pull 2 results from a sub query in a sql statement?
I have:
"SELECT
(SELECT bid FROM auction_bids WHERE itemID=a.id ORDER BY bid DESC LIMIT 1) as topbid,
a.* FROM auction_items a ORDER BY a.date DESC LIMIT 15"
The part where it returns the topbid, i'd also like it to pull not only bid (as topbid) but also date (as topdate) as well. How can I do that? Do I need another sub query or can it pull both in one?
Dependent subquery (depending on some values outside, like a.id in your case) is not a very efficient way to find maximum values in subsets.
Instead use a subquery with GROUP BY:
SELECT b.topbid, b.topdate, a.*
FROM auction_items a
LEFT JOIN
( SELECT itemID, MAX(bid) as topbid, MAX(date) as topdate
FROM auction_bids
GROUP BY itemID ) b
ON a.id = b.itemID
ORDER BY a.date DESC
LIMIT 15

Combining UNION and LIMIT operations in MySQL query

I have a Jobs and a Companies table, and I want to extract 20 jobs that meet the following criteria:
Jobs only from two (2) named companies
There can at most be 10 jobs per company
I have tried the following SELECT with UNION DISTINCT, but the problem is that the LIMIT 0,10 applies to the whole result set. I want it to apply to each of the companies.
If there aren't 10 jobs per company, then the query should return all the jobs it finds.
SELECT c.name, j.title, j.`desc`, j.link
FROM jobs_job j
INNER JOIN companies_company c ON j.company_id = c.id
WHERE c.name IN ('Company1')
UNION DISTINCT
SELECT c.name, j.title, j.`desc`, j.link
FROM jobs_job j
INNER JOIN companies_company c ON j.company_id = c.id
WHERE c.name IN ('Company2')
ORDER by name, title
LIMIT 0,10
I am new to MySQL, so realise there may be a smarter way to do this instead of with UNION, so any suggestions for improvements are definitely welcome.
Quoting the docs,
To apply ORDER BY or LIMIT to an
individual SELECT, place the clause
inside the parentheses that enclose
the SELECT:
(SELECT a FROM t1 WHERE a=10 AND B=1 ORDER BY a LIMIT 10)
UNION
(SELECT a FROM t2 WHERE a=11 AND B=2 ORDER BY a LIMIT 10);
Improving on Alex's answer and based on Joe's observation, the following should work in SQLite:
SELECT * FROM
(SELECT a FROM t1 WHERE a=10 AND B=1 ORDER BY a LIMIT 10)
UNION
(SELECT a FROM t2 WHERE a=11 AND B=2 ORDER BY a LIMIT 10);
In Teradata we can't use union with top queries as it, if you do you get an error, which needs to be tweaked as shown below. Adding solution for Teradata users.