Sorry, I didn’t understand that you are using MySQL - the updated answer given below.
Assuming that each tag can only be specified once for each photo (i.e. the photo cannot be marked as dirty several times):
SELECT P.id, P.[filename] FROM Photos P INNER JOIN Tagsphotos TP ON TP.photo = P.id INNER JOIN Tags T ON TP.tag = T.id INNER JOIN ( SELECT 'dirty' name, 10 [weight] UNION SELECT 'road' name, 10 [weight] UNION SELECT 'perspective.two-point' name, 10 [weight] UNION SELECT 'light.front' name, 1 [weight] UNION SELECT 'light.side' name, 1 [weight] ) R ON T.name = R.name GROUP BY P.id, P.[filename] HAVING SUM(R.[weight]) >= 31
source share