Moreso a psuedo-code question than actual code. I have some custom post meta attached to attachments, and created a list table column for this meta. The meta is either 1, or null (not set), but I am trying to enable sorting for said column.

Is there a way to utilize meta_query for WP_Query to essentially LEFT JOIN, where I get all values (1 or null), and then I can utilize orderby=meta_value_num for ordering?

The obvious way it would work is hooking into posts_clauses, adding a JOIN, and doing the orderby as well - just curious if this would be possible while using direct WP_Query functionality!


  • Why are you adding a custom column (and to which table) when there's the post_meta table anyway? One entry equals one row in this table.
    – kaiser
    Jun 13, 2013 at 13:29
  • Media List Table, not database table Jun 13, 2013 at 13:30

2 Answers 2


You can use pre_get_posts with a callback:

defined( 'ABSPATH' ) OR exit;
/** Plugin Name: (#102854) Order Posts by Foo */

add_filter( 'pre_get_posts', 'wpse_102854_orderby_foo' );
function wpse_102854_orderby_foo( $query )
    if ( 
        ! $query->is_main_query()
        OR ! is_admin()
        OR 'edit.php?post_type=YOUR_POST_TYPE' !== $GLOBALS['parent_file']
        // Other conditions that force an abort, Example:
        // OR 'foo' !== $query->get( 'some_query_var' )
        return $query;

    $query->set( 'orderby', 'meta_value_num' );
    // etc.

    return $query;
  • Correct. I think this will NOT work however. In order for this to work, meta_query would need to support 'join_type' or something similar. Right now 'Inner Join' is hard coded. wp-includes/meta.php line 731. Jun 13, 2013 at 13:55
  • @EricHolmes Take a look at this plugin I wrote, which supports "Match" and "Filter" to get either posts with either ALL taxonomies attached or posts with ANY taxonomy attached. Should get you on the right track.
    – kaiser
    Jun 13, 2013 at 14:12
  • Thanks @kaiser, you pointed me in the right direction with relation. Updated my answer below with the correct method using pre_get_posts. Jun 13, 2013 at 14:31

You can do it either way!

Using posts_clauses, manually write your JOIN statement (using $wpdb->prepare() - be safe!) , and add/customize the orderby clause as well.

Using meta_query there are a couple things needed. First, as kaiser mentions, you must use relation within meta_query in order for it to work. Second, even though meta_query is defined, you still need to specify the meta_key argument, or else orderby=meta_value will not work. I assume this is because you can have multiple joins happening at once, which could be using different meta keys.

Here is how I accomplished it:

function handle_my_sortable_column( $query ) {
    global $pagenow;
    if( is_admin() && 'upload.php' == $pagenow && 'my_meta_key' == get_query_var( 'orderby' ) ) {
        $query->set( 'meta_query', array(
            'relation' => 'OR',
                'key' => my_meta_key',
                'value' => null,
                'compare' => 'EXISTS'
                'key' => 'my_meta_key',
                'value' => '', // must be '' value, null does not work
                'compare' => 'NOT EXISTS'
        ) );
        $query->set( 'meta_key', 'my_meta_key' ); // required for orderby
        $query->set( 'orderby', 'meta_value_num' );
  • 1
    Afaik your only problem is that the relation is set to AND instead to OR. This should be the only thing you need to change.
    – kaiser
    Jun 13, 2013 at 14:08
  • Interesting - relation is found under tax_query but not meta_query - testing this now. Jun 13, 2013 at 14:15
  • Updating my answer now. Jun 13, 2013 at 14:25
  • 1
    Well, that the value needs to be defined empty is even stated in Codex ;)
    – kaiser
    Jun 13, 2013 at 14:40
  • it mentions trying both null and ''. Thought I'd point out that bull didn't work for NOT EXISTS but did for EXISTS - strange. Jun 13, 2013 at 14:45

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.