I’ve used this query to randomly select a total of $limit-images (attachments), each from a unique and randomly selected parent.
$query="SELECT {$wpdb->posts}.post_parent, {$wpdb->posts}.ID
FROM {$wpdb->posts}
INNER JOIN {$wpdb->term_relationships} ON ({$wpdb->posts}.post_parent = {$wpdb->term_relationships}.object_id)
INNER JOIN {$wpdb->term_taxonomy} ON ({$wpdb->term_relationships}.term_taxonomy_id = {$wpdb->term_taxonomy}.term_taxonomy_id)
WHERE {$wpdb->posts}.post_type = 'attachment'
AND {$wpdb->term_taxonomy}.taxonomy = 'category' AND {$wpdb->term_taxonomy}.term_id IN ('{$wpdb->escape($category_filter)}')
AND {$wpdb->posts}.post_password = ''
AND {$wpdb->posts}.post_mime_type IN ('image/jpeg', 'image/gif', 'image/png')
GROUP BY {$wpdb->posts}.post_parent
ORDER BY {$order_by}
LIMIT {$limit};";
Unfortunately it has three faults:
-
I think the password-check is incorrect as it tests the attachment and not the parent_post, right? (does WordPress even support password protected gallery attachments?)
-
it certainly doesn’t check the parent for
post_status = "publish" -
it correctly selects random posts, but always the same pictures within them (the first one).
So – I humbly ask for your SQL-fu. How does one both select a random parent (first checking for published status) and then a random image ID owned by that parent, all in one query?
(I could select all attachments, ordered randomly and loop through them all and just grab the first $limitfrom unique parents. But that leads to parents with lots of images getting selected too often.)
“When the answer escapes you, change the question…”
I just released a plugin that enables bulk selection of a “featured post image”, directly from the media library. The core of my function went from ~45 lines to this;
foreach($potential_parents as $parent){
if(has_post_thumbnail($parent->ID)) {
$image = get_post_thumbnail_id($parent->ID);
}
}
It’s not random but the site looks better and visitors have an easier time navigating content now that the thumbnails are consistent.
It’s not one query, but it’s a heck of a lot faster than the WordPress-hackery I posted earlier, and not very much slower than the original. I suppose it’s the price to pay for correctness and while being SQL-ignorant. 😛
So basically, first grab one largish result set with all published posts in the categories. Then a bunch of smaller queries, fetching a single attachment ID every loop until the
$limithas been filled.If you’ve got lots of posts in these categories without attachments, you’ll waste some time here. But in our case it seems to be manageable.
Still looking for that efficient single-query solution though. 🙂