Order By Multiple Meta Fields

时间:2015-06-23 作者:leclaeli

我有两个自定义字段:

  • meta_key1 是布尔值(01).
  • meta_key2 是日期值-20150623 例如meta_key2 字段具有显式值。看起来他们被视为一个空字符串\'\'.

    我想找到所有有meta_key2 (日期)值大于今天或具有meta_key1 值为true。

    这是我希望它们显示的顺序。

    1. key2.meta_value >= today ASC
    2. key1.meta_value = TRUE ordered by date ASC (先给出日期的)0 因此,首先进入ASC 顺序我尝试使用COALESCE 为了解释这一点,我已经取得了一些成功,但有一点让我很困惑。我找不到key1.meta_value = FALSEkey2.meta_value is >= today 在中显示ASC 顺序

      我的问题是:

      $meta_key1 = \'prog_ongoing\';
      $meta_key2 = \'prog_date_start\';
      $start_date = date(\'Ymd\');
      
      $postids = $wpdb->get_col( $wpdb->prepare( 
      "
      SELECT      DISTINCT key1.post_id
      FROM        $wpdb->postmeta key1
      INNER JOIN  $wpdb->postmeta key2
                  ON key2.post_id = key1.post_id
                  AND key2.meta_key = %s
      WHERE       key1.meta_key = %s
                  AND key1.meta_value is TRUE
                  OR key2.meta_value >= %d
      ORDER BY    COALESCE(NULLIF(key1.meta_value, 0), 0) DESC, COALESCE(NULLIF(key2.meta_value, \'\'), $start_date) ASC, key2.meta_value ASC 
      ",
      $meta_key2,
      $meta_key1,
      $start_date
      ) );
      
      我不确定我的COALESCE 上的声明key1.meta_value 正在做任何事。感谢您对此的任何见解。

3 个回复
最合适的回答,由SO网友:bonger 整理而成

查询的一个问题是,self连接与WHERE 提供一个交叉数据集(由DISTINCT), 所以使用起来会更简单wp_post 作为连接与关键点精确匹配的连接的基础,例如

    SELECT      p.ID, key1.meta_value as prog_ongoing, key2.meta_value as prog_date_start
    FROM        $wpdb->posts p
    INNER JOIN  $wpdb->postmeta key1
                ON key1.post_id = p.ID
                AND key1.meta_key = %s
    INNER JOIN  $wpdb->postmeta key2
                ON key2.post_id = p.ID
                AND key2.meta_key = %s
它给出了一个线性数据集。然后您可以添加(或不添加)WHERE 限制数据的条款:

    WHERE       key1.meta_value IS TRUE OR key2.meta_value >= %d
对于ORDER BY 使用CASE 语句单字段排序:

    ORDER BY    CASE
                    WHEN key2.meta_value >= %d THEN CONCAT(\'A\', key2.meta_value)
                    WHEN key1.meta_value AND key2.meta_value THEN CONCAT(\'B\', key2.meta_value)
                    WHEN key1.meta_value THEN \'C\'
                    ELSE \'D\'
                END ASC
或者类似的,上述需要prepare 参数为:

    $meta_key1,
    $meta_key2,
    $start_date, $start_date
您可以使用posts_orderby 使用筛选器执行类似操作WP_Query (虽然它使用了一种生成交叉数据集的方法,但要求它必须使用GROUP BY, 这会使事情复杂化)。比如说

$args = array(
    \'posts_per_page\' => -1,
    \'post_type\' => \'cpt_program\',
    \'meta_query\' => array(
        \'ongoing\' => array(
            \'key\' => \'prog_ongoing\',
        ),
        \'start_date\' => array(
            \'key\' => \'prog_date_start\',
        )
    ),
);

add_filter( \'posts_orderby\', $func = function ( $orderby, $query ) {
    $start_date = date(\'Ymd\');
    global $wpdb;
    $orderby = $wpdb->prepare(
        "
        CASE
            WHEN mt1.meta_value >= %d THEN CONCAT(\'A\', mt1.meta_value)
            WHEN {$wpdb->postmeta}.meta_value AND mt1.meta_value THEN CONCAT(\'B\', mt1.meta_value)
            WHEN {$wpdb->postmeta}.meta_value THEN \'C\'
            ELSE \'D\'
        END ASC
        "
        , $start_date
    );
    return $orderby;
}, 10, 2 );
$query = new WP_Query( $args );
remove_filter( \'posts_orderby\', $func, 10, 2 );

SO网友:Manny Fleurmond

解决方案的第一关。它使用4.2中引入的新元排序:

 <?php
    $args = array(
        \'posts_per_page\' => -1,
        \'meta_query\' => array(
            \'relation\' => \'OR\',
            \'ongoing\' => array(
                \'key\'     => \'prog_ongoing\',
                \'value\'   => 1
            ),
            \'start_date\' => array(
                array(
                    \'key\' => \'prog_date_start\',
                    \'value\'   => date(\'Ymd\'),
                    \'type\'    => \'numeric\',
                    \'compare\' => \'>=\'
                )
            )
        ),
        \'orderby\' => \'start_date ongoing\',
        \'order\'   => \'ASC\',
    );

    $programs = new WP_Query($args);
    ?>
    <?php while($programs->have_posts()): $programs->the_post(); ?>
        <h1><?php the_title(); ?></h1>
    <?php endwhile; ?>
我想我的逻辑是对的,但如果不是这样,请告诉我

编辑您可以在以下make中查看Wordpress 4.2中按多个自定义字段排序的新语法

SO网友:passatgt

为什么不使用WP_Query()? 这样更简单:

    <?php
    $args = array(
        \'posts_per_page\' => -1,
        \'meta_query\' => array(
            \'relation\' => \'OR\',
            array(
                \'key\'     => \'prog_ongoing\',
                \'value\'   => 1
            ),
            array(
                \'relation\' => \'AND\',
                array(
                    \'key\' => \'prog_date_start\',
                    \'value\'   => date(\'Ymd\'),
                    \'type\'    => \'numeric\',
                    \'compare\' => \'<=\'
                ),
                array(
                   \'key\' => \'prog_date_start\',
                    \'value\'   => 1,
                    \'type\'    => \'numeric\',
                    \'compare\' => \'>\'
                )
            )
        ),
        \'orderby\' => \'meta_value_num date\',
        \'order\'   => \'ASC\',
        \'meta_key\' => \'prog_date_start\'
    );

    $programs = new WP_Query($args);
    ?>
    <?php while($programs->have_posts()): $programs->the_post(); ?>
        <h1><?php the_title(); ?></h1>
    <?php endwhile; ?>

结束

相关推荐

在插件中写入MySQL凭据

我必须创建一个自定义插件来打印来自不同于wordpress数据库的数据。我正在使用wpdb。从安全角度来看,以这种方式在插件文件中写入数据库credantials可以吗?还是应该以不同的方式进行?<?php function myfun() { $fundb = new wpdb(\'root\', \'password\', \'database\', \'localhost\'); $result = $fundb ->get_r