Question

Do you have any idea how I can improve the following sql select query? It takes a while to get results even in sql management studio. So, it takes longer when I call it from the website. I get the top 15 results but it still takes time to get results. Is it because of the sub-queries?

SELECT top 15  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

WHERE (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))>1

ORDER BY myCount DESC
Was it helpful?

Solution

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).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top