我在做一个WordPress项目时遇到了一个边缘案例。我使用高级自定义字段来存储关于帖子的元数据,这存储在"postmeta"表中(而帖子存储在"post"表中;此处以"otca_"为前缀)。
这里的帖子是事件,具有强制性evt_date和可能具有evt_date_fin("fin"在法语中代表"end",很抱歉蹩脚的命名约定)。
我的目标是选择一系列事件,只保留那些具有evt_date设置或evt_date_fin设置的事件(在后一种情况下,无论evt_date),同时按evt_date排序,以便以分页,排序的方式显示它们。
这是我想到的:
$today = date('Ymd');
$perPage = 12;
$offset = $perPage * ($paged-1); // $paged equals 1, 2, … n (the current page)
$querystr = "
SELECT SQL_CALC_FOUND_ROWS * FROM otca_posts AS post
INNER JOIN otca_postmeta AS meta ON (post.ID = meta.post_id)
WHERE post.post_type = 'agenda'
AND post.post_status = 'publish'
AND (
(meta.meta_key = 'evt_date' AND CAST(meta.meta_value AS CHAR) >= '". $today ."')
OR (meta.meta_key = 'evt_date_fin' AND CAST(meta.meta_value AS CHAR) >= '". $today ."')
)
ORDER BY (meta.meta_key = 'evt_date' AND CAST(meta.meta_value AS CHAR)) ASC
LIMIT ". $perPage ." OFFSET ". $offset;
$evts = $wpdb->get_results($querystr);
$total = $wpdb->get_var('SELECT FOUND_ROWS()');
// then looping over the $evts and using $perPage / $total to build the pagination links
因此,对于存储在otca_post中的给定帖子,otca_postmeta表中有多条引用该帖子的记录(使用post_id),它们的meta_key/meta_value对不同(一个用于evt_date,另一个用于evt_date_fin)。我用它们来过滤掉查询中的帖子,这很好。
ORDER BY子句实际上不起作用。
我想知道我怎么能使它,使帖子是由evt_date,一块信息存储在otca_postmeta排序;evt_date不是一行,而是存储在行"meta_key"中的值,这意味着我需要以某种方式执行子选择,以便……排序。
谢谢。
我经常在我的WordPress插件中这样做-你需要为你关心的每个meta_key
's加入posts
表到postmeta
表,在这种情况下"evt_date"one_answers"evt_date_fin"。一旦您将它们连接起来,您可以在WHERE
子句中使用它们来与DATE(CURRENT_TIMESTAMP)
进行比较。使用MySql函数STR_TO_DATE()
将把存储在meta_value
中的字符串转换为DATE
数据类型——本例假设您使用Y-m-d
格式。
$perPage = 12;
$offset = $perPage * ($paged-1);
// create the SQL query by joining posts to postmeta
$querystr = <<<SQL
SELECT SQL_CALC_FOUND_ROWS
p.*,
STR_TO_DATE(s.meta_value, '%Y-%m-%d') AS start_date,
STR_TO_DATE(e.meta_value, '%Y-%m-%d') AS end_date
FROM otca_posts AS p
-- join postmeta for the start
JOIN otca_postmeta AS s ON p.ID = s.post_id AND s.meta_key = 'evt_date'
-- join postmeta for the end
JOIN otca_postmeta AS e ON p.ID = e.post_id AND e.meta_key = 'evt_date_fin'
WHERE
-- is the start greater than or equal to today?
STR_TO_DATE(s.meta_value, '%Y-%m-%d') >= DATE(CURRENT_TIMESTAMP) OR
-- or is the end greater than or equal to today?
STR_TO_DATE(e.meta_value, '%Y-%m-%d') >= DATE(CURRENT_TIMESTAMP)
-- order the results by the start, then the end, then the post title
ORDER BY start_date, end_date, p.post_title
-- paginate the results
LIMIT $perPage OFFSET $offset
SQL;
// get posts that match
$evts = $wpdb->get_results( $querystr );
// get the total number of results
$total = $wpdb->get_var( 'SELECT FOUND_ROWS()' );