First, you only need to run the subquery once:
SELECT top 15 *
FROM (SELECT t1.TagId, t1.TagName,
(SELECT COUNT(*)
FROM TagsToPost
WHERE TagsToPost.TagId=t1.TagId AND
EXISTS (SELECT *
FROM Posts
WHERE PostId=TagsToPost.PostId AND
Posts.Time > '2014-01-01 00:00:00.000' AND
Posts.TimePointId=@TimePointId
)
) as myCount
FROM Tags as t1
) t
WHERE COUNT(*) > 1
ORDER BY myCount DESC;
I'm not sure that SQL Server will optimize it to eliminate generating one result set so this might cut the query time in half.
Then, you can eliminate one level of exists
by using a standard group by
and join
:
SELECT top 15 t.TagId, t.TagName, COUNT(*) as myCount
FROM tags t join
TagsToPost tp
on TagsToPost.TagId = t.TagId AND
WHERE EXISTS (SELECT 1
FROM Posts p
WHERE p.PostId = tp.PostId AND
p.Time > '2014-01-01 00:00:00.000' AND
p.TimePointId=@TimePointId
)
GROUP BY t.TagId, t.TagName
HAVING myCOunt > 1
ORDER BY myCount DESC;
You could do something similar with posts
. But it is probably sufficient to create an index Posts(PostId, TimePointId, Time)
.