If you have a large number of users to delete, you might consder using the wp user delete wp-cli command to avoid script timeouts.
Here’s an example of a SQL query to delete all users without posts of any type and status.
You can therefore try this untested one-liner:
wp user delete $(wp db query "SELECT ID FROM wp_users WHERE ID NOT IN (SELECT DISTINCT post_author FROM wp_posts ) AND ID NOT IN (1,2,3)" | tail -n +2 ) --reassign=1
or in expanded form:
wp user delete $(wp db query
"SELECT ID
FROM wp_users
WHERE ID NOT IN (
SELECT DISTINCT post_author FROM wp_posts
) AND ID NOT IN (1,2,3)" | tail -n +2
) --reassign=1
Note that we added an extra AND ID NOT IN (1,2,3)
restriction to make sure these users are not deleted (e.g. admin users). You will have to adjust it to your needs and also the table prefix wp_
.
When I briefly tested this for couple of users, I noticed I had to add the tail -n +2
part to avoid the top 3 lines in the header and the table border of the wp db query
output.
Here we reassign all posts to user 1, to avoid the notice:
--reassign parameter not passed. All associated posts will be deleted. Proceed? [y/n]
Hope you can adjust it further to your needs, like relaxing the user delete conditions by adding WHERE post_status="publish"
.
Note: Remember to backup before testing!