Reputation: 29331
DELETE from Users
Where Id in (
SELECT TOP 200 u.id
FROM users u JOIN
playlists pl
ON u.id = pl.UserId LEFT OUTER JOIN
playlistitems pli
ON pli.PlaylistId = pl.id
GROUP BY u.id
HAVING count(pl.id) = 1 AND
count(pli.id) = 0
)
Are there any pitfalls in this SQL query which would cause it to run really slowly? It takes me 1m32s to delete 200 rows, but there's 260,000 that I need to clean up..
Upvotes: 0
Views: 71
Reputation: 6415
Index each of the tables on the ID column. Preferably a clustered index, but not essential.
given that you already have indexes, try something like this:
;with cte as
(
select
u.id,
rank() over (partition by u.id) as rk
from users u
join playlists pl on pl.UserId = u.ID
join playlistites pli on pli.PlaylistID = pl.ID
)
delete from cte
where rk > 200
Upvotes: 1
Reputation: 1066
-- insert users to delete in #temp table
SELECT u.id
INTO #toDelete
FROM users u JOIN
playlists pl
ON u.id = pl.UserId LEFT OUTER JOIN
playlistitems pli
ON pli.PlaylistId = pl.id
GROUP BY u.id
HAVING count(pl.id) = 1 AND
count(pli.id) = 0
-- increment or decrement at will
set @rowcount 200
select 'dummy' -- force @@rowcount > 0
while @@rowcount > 0
begin
delete
from Users
where exists (select * from #toDelete td where td.id = users.id)
end
set @rowcount 0
Upvotes: 0
Reputation: 2509
I think it is pointless to join from users
why don't you do this instead:
DELETE from Users
Where Id in (
SELECT TOP 200 pl.UserId
FROM playlists pl
LEFT OUTER JOIN
playlistitems pli
ON pli.PlaylistId = pl.id
GROUP BY pl.UserId
HAVING count(pl.id) = 1 AND
count(pli.id) = 0
)
Upvotes: 1