I whipped something up for you. It's fairly complex, so I'll explain it for you.
You shouldn't attempt this on your live website and should do it on a test version of your database. Make backups in case something goes wrong. Here's the query:
Code:
UPDATE categories
SET categories_status = 0
WHERE categories_id NOT IN
(
SELECT categories_id FROM
(
SELECT DISTINCT categories_id
FROM products_to_categories
NATURAL JOIN categories
) as foo
)
AND parent_id != 0;
Basically, if the category isn't in the sub-select statement (the one two parenthesis in), turn it off.
The sub-select gathers all the distinct categories that are actually being used. If a category has a product, it will be selected. Since we're looking for all the categories that aren't being used (via NOT IN), the query will turn off the categories that do not get selected.
And, finally, don't turn off categories that are parents at the highest level in Zen Cart (the categories you'd see on the front page) even if they don't hold products themselves.
MySQL doesn't like when you try and update a table and then sub-select a WHERE clause from the same table you're updating. In the above query, I have made a temporary table called 'foo' to work around this.
I really hope this helps.
Again: don't do this on your live website!