ORDER BY带有‘EXISTS’和‘NOT EXISTS’的嵌套命名元查询

时间:2021-07-27 作者:Artem

我的每个帖子(在线商店项目)都有元键:

  1. tdlrm_mp - 我自己的menu\\u位置(从1开始,与wp\\u posts menu\\u位置不同,可能不存在)
  2. 1C_quantity_total - 库存商品数量我希望商品按以下顺序输出:

    首先tdlrm_mp 存在,排序人tdlrm_mp 从最低到最高tdlrm_mp 不存在,订购者1C_quantity_total, 从高到低

以下是我的元查询的参数:

$args[\'meta_query\'] = array(
                \'tdlrm_mp_key\' => array(
                    \'relation\' => \'OR\',
                    \'tdlrm_mp_exists\' => array(
                        \'key\'     => \'tdlrm_mp\',
                        \'type\'    => \'NUMERIC\',
                        \'compare\' => \'EXISTS\',
                    ),
                    \'tdlrm_mp_not_exists\' => array(
                        \'key\'     => \'tdlrm_mp\',
                        \'compare\' => \'NOT EXISTS\',
                    )
                ),
                \'quantity_total\' => array(
                    \'key\'     => \'1C_quantity_total\',
                    \'type\'    => \'NUMERIC\',
                    \'compare\' => \'EXISTS\',
                ),
            );
            $args[\'orderby\'] = array(
                \'tdlrm_mp_key\' => \'ASC\',
                \'quantity_total\' => \'DESC\'
            );
这似乎不起作用,这些帖子只能按数量订购。我做错了什么?

我试过普通的

$args[\'orderby\'] = array(
   \'tdlrm_mp\' => \'ASC\',
   \'1C_quantity_total\' => \'DESC\',
);
但它首先输出tdlrm_mp 不存在

我也找到了这个question , 但我不知道它是否适用于这里

1 个回复
最合适的回答,由SO网友:Sally CJ 整理而成

请注意orderby 数组需要引用中的数组meta_query 其中包含直接key 项目,例如。\'key\' => \'tdlrm_mp\'. 例如,您应该使用\'tdlrm_mp_exists\' => \'ASC\', 而不是\'tdlrm_mp_key\' => \'ASC\' 在您的$args[\'orderby\'].

然而,这实际上并不能按照您希望的方式对帖子进行排序,但我只是向您展示了应该使用的正确语法。

但不要担心,你想做的是可能的:)

下面是如何设置meta_query 收件人:

$args[\'meta_query\'] = array(
    array(
        \'relation\'     => \'OR\',
        // select posts that have the tdlrm_mp meta
        \'has_tdlrm_mp\' => array(
            \'key\'  => \'tdlrm_mp\',
            \'type\' => \'NUMERIC\',
        ),
        // select posts that don\'t have the meta
        \'no_tdlrm_mp\'  => array(
            \'key\'     => \'tdlrm_mp\',
            \'compare\' => \'NOT EXISTS\',
        ),
    ),
    array(
        \'relation\'              => \'OR\',
        // select posts that have the 1C_quantity_total meta
        \'has_1C_quantity_total\' => array(
            \'key\'  => \'1C_quantity_total\',
            \'type\' => \'NUMERIC\',
        ),
        // select posts that don\'t have the meta
        \'no_1C_quantity_total\'  => array(
            \'key\'     => \'1C_quantity_total\',
            \'compare\' => \'NOT EXISTS\',
        ),
    ),
);
orderby 到none 因为我们将使用完全定制的。

  • Before 你跑吧new WP_Query(), 使用posts_orderby filter 要修改ORDER BY 子句,基本上我们使用CASE operator 要实现您想要的(相当复杂)排序,请执行以下操作:

    $_filter = true; // enable the filter below
    add_filter( \'posts_orderby\', function ( $orderby, $query ) use ( &$_filter ) {
        if ( $_filter ) {
            global $wpdb;
    
            $meta_clauses          = $query->meta_query->get_clauses();
            $has_tdlrm_mp          = $meta_clauses[\'has_tdlrm_mp\'][\'alias\'];
            $has_1C_quantity_total = $meta_clauses[\'has_1C_quantity_total\'][\'alias\'];
    
            // 1st, sort by the meta key, and posts without the meta are placed at
            // the bottom (or 3rd position).
            $orderby = "
    CASE {$has_tdlrm_mp}.meta_key
        WHEN \'tdlrm_mp\'          THEN 1
        WHEN \'1C_quantity_total\' THEN 2
        ELSE 3
    END ASC";
    
            // 2nd, sort by the meta value, only for the posts in position 1 and 2
            // above.
            $orderby .= ",
    CASE {$has_tdlrm_mp}.meta_key
        WHEN \'tdlrm_mp\'          THEN {$has_tdlrm_mp}.meta_value+0
    END ASC,
    CASE {$has_1C_quantity_total}.meta_key
        WHEN \'1C_quantity_total\' THEN {$has_1C_quantity_total}.meta_value+0
    END DESC";
    
            // 3rd, now optionally sort the posts in the 3rd position above. Here,
            // we sort them by the post date.
            $orderby .= ", {$wpdb->posts}.post_date DESC";
        }
    
        return $orderby;
    }, 10, 2 );
    
    $query = new WP_Query( $args );
    $_filter = false; // disable the filter above
    
  • 更新

    抱歉,我修改了几次答案,但实际上我仍然忘记更正表别名(在上面的步骤3中)。

    现在我已经更正了它,此外,我还使用了WP_Meta_Query::get_clauses() 而不是对(表)别名进行硬编码。非常感谢@Artem 还有他的other question!

    相关推荐

    我可以将主循环更改为‘orderby’自定义回调吗?

    我有一个自定义的帖子类型title 是一个名称,我想按中的最后一个单词对循环进行排序title, 姓氏。在自定义查询中,我可以轻松地将名称分开并按最后一个单词进行过滤,但我不想重新编写归档页面的主循环/分页。是否可以将回调传递给orderby 操作中的参数pre_get_posts 还是这是一个失败的事业?谢谢