查询自定义元字段并按自定义元对其进行排序

时间:2013-05-18 作者:Heather Goff

我有多个自定义日期和时间字段的事件帖子。为了获取本周发生的所有事件,我正在查询不同的日期字段。这是我的代码:

$today=date("Y-m-d");
$nextweek= date("Y-m-d", strtotime("+7 days"));

$args2 = array(

\'post_type\' => \'post\',
\'meta_query\' => array(
\'relation\' => \'OR\',

array(
\'key\' => \'date2\',
\'value\' => array( $today, $nextweek ),
\'compare\' => \'BETWEEN\'
),
array(
\'key\' => \'date3\',
\'value\' => array( $today, $nextweek ),
\'compare\' => \'BETWEEN\'
),
array(
\'key\' => \'date1\',
\'value\' => array( $today, $nextweek ),
\'compare\' => \'BETWEEN\'

)
)
);
$query2 = new WP_Query( $args2 ); ?>
在这之后放置var\\u dump($query2->request)时,我得到以下字符串:

SELECT SQL_CALC_FOUND_ROWS wp_posts.ID 
FROM wp_posts 
INNER JOIN wp_postmeta ON (wp_posts.ID = wp_postmeta.post_id) 
INNER JOIN wp_postmeta AS mt1 ON (wp_posts.ID = mt1.post_id) 
INNER JOIN wp_postmeta AS mt2 ON (wp_posts.ID = mt2.post_id) 
WHERE 1=1 AND wp_posts.post_type = \'post\' 
AND (wp_posts.post_status = \'publish\' OR wp_posts.post_status = \'private\') 
AND ( 
  (wp_postmeta.meta_key = \'date2\' AND CAST(wp_postmeta.meta_value AS CHAR) BETWEEN \'2013-05-21\' AND \'2013-05-28\') 
  OR (mt1.meta_key = \'date3\' AND CAST(mt1.meta_value AS CHAR) BETWEEN \'2013-05-21\' AND \'2013-05-28\') 
  OR (mt2.meta_key = \'date1\' AND CAST(mt2.meta_value AS CHAR) BETWEEN \'2013-05-21\' AND \'2013-05-28\') 
) 
GROUP BY wp_posts.ID 
ORDER BY wp_posts.post_date DESC LIMIT 0, 10
这是正确的帖子,但现在我想对date1字段上的结果进行排序。我试过了,但没用。我最终发布了所有事件,但也没有进行排序。我还尝试了orderby的“meta\\u值”,但运气不佳。date1字段中的值为日期格式YYYY MM DDA,如有任何帮助,将不胜感激。

$args2 = array(
\'order\' => \'ASC\',
\'meta_key\' => \'date1\',
\'orderby\' => \'meta_value_num\',
\'post_type\' => \'post\',
\'meta_query\' => array(
\'relation\' => \'OR\',

array(
\'key\' => \'date2\',
\'value\' => array( $today, $nextweek ),
\'compare\' => \'BETWEEN\'
),
array(
\'key\' => \'date3\',
\'value\' => array( $today, $nextweek ),
\'compare\' => \'BETWEEN\'
),
array(
\'key\' => \'date1\',
\'value\' => array( $today, $nextweek ),
\'compare\' => \'BETWEEN\',

)
)

);

$query2 = new WP_Query( $args2 ); ?>
当我将var\\u dump($query2->request)放在这之后时,我得到:

SELECT SQL_CALC_FOUND_ROWS wp_posts.ID 
FROM wp_posts 
INNER JOIN wp_postmeta ON wp_posts.ID = wp_postmeta.post_id 
INNER JOIN wp_postmeta AS mt1 ON (wp_posts.ID = mt1.post_id) 
INNER JOIN wp_postmeta AS mt2 ON (wp_posts.ID = mt2.post_id) 
INNER JOIN wp_postmeta AS mt3 ON (wp_posts.ID = mt3.post_id) 
WHERE 1=1 
AND wp_posts.post_type = \'post\' 
AND (wp_posts.post_status = \'publish\' OR wp_posts.post_status = \'private\') 
AND (wp_postmeta.meta_key = \'date1\' 
  OR (mt1.meta_key = \'date2\' AND CAST(mt1.meta_value AS CHAR) BETWEEN \'2013-05-21\' AND \'2013-05-28\') 
  OR (mt2.meta_key = \'date3\' AND CAST(mt2.meta_value AS CHAR) BETWEEN \'2013-05-21\' AND \'2013-05-28\') 
  OR (mt3.meta_key = \'date1\' AND CAST(mt3.meta_value AS CHAR) BETWEEN \'2013-05-21\' AND \'2013-05-28\') 
) 
GROUP BY wp_posts.ID 
ORDER BY wp_postmeta.meta_value+0 ASC LIMIT 0, 10 

1 个回复
SO网友:s_ha_dum

您的元字段是JOINing as公司mt* 该查询中的别名。寻找以下线条:

INNER JOIN wp_postmeta AS mt1 ON ...
但是ORDER BY 参数为wp_postmeta.meta_value, 这其实没什么意义。如果这不是一个bug,我称之为糟糕的设计或非常有限的设计,但请继续。

要特别针对你的一个元价值,第一个,你需要ORDER BY 要成为。。。

ORDER BY mt1.meta_value
你不想meta_value_num, 顺便说一下,因为你没有数字。那里有破折号。MySQL将把日期“2013-12-15”+0解释为“2013”。放SELECT (\'2013-12-15\')+0 进入PhpMyAdmin的SQL面板并运行查询。

要对现有数据执行此操作,需要为查询创建一个过滤器。向查询中添加参数。。。

$args2 = array(
  \'my_orderby_field\' => \'mt1\',
  \'order\' => \'ASC\',
  \'meta_key\' => \'date1\',
  \'orderby\' => \'meta_value\',
  /* ... the rest */

function order_by_one_meta($orderby,$qry) {
  $myorder = $qry->get(\'my_orderby_field\');
  if (!empty($myorder)) {
    global $wpdb;
    $orderby = str_replace($wpdb->postmeta,$myorder,$orderby);
  }
  return $orderby;
}
add_filter(\'posts_orderby\',\'order_by_one_meta\',100,2);
将自己的字段添加到查询中是一种黑客行为。我不知道它是设计出来的,或者是无意中产生的副作用,所以它确实算是一段有点危险的代码。另一种方法是创建回调:

function order_by_one_meta($orderby) {
  $orderby = str_replace($wpdb->postmeta,$myorder,$orderby);
  return $orderby;
}
应用它,然后在需要的地方将其移除。

add_filter(\'posts_orderby\',\'order_by_one_meta\',100);
$query2 = new WP_Query( $args2 ); 
remove_filter(\'posts_orderby\',\'order_by_one_meta\',100);
不那么危险,也没那么有趣(

我无法测试这一点,因为我在数据库中没有您的数据,但SQL应该是正确的。

我不知道为什么你需要多个日期键。多次使用同一个键_scheduled_event_dates-- 应该会给您同样的效果,并且会使查询和代码更加高效。

结束

相关推荐

使用新的WP-Query()从循环中过滤后期格式;

嗨,我目前正在为我的博客构建一个主题。下面的代码指向最新的帖子(特色帖子)。因为这将有一个不同的风格比所有其他职位。然而我想过滤掉帖子格式:链接使用我在循环中定义的WP查询,因为它给我带来了更多的灵活性。我该怎么做呢? <?php $featured = new WP_Query(); $featured->query(\'showposts=1\'); ?> <?php while ($featured->have_post