ORDER BY子句受另一个表中的子选择约束

时间:2014-07-26 01:51:38

标签: mysql sql wordpress

在处理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”行中的值,这意味着我需要以某种方式执行子选择以便...订购。

谢谢。

1 个答案:

答案 0 :(得分:1)

我在我的WordPress插件中经常这样做 - 您需要将posts表加入postmeta表,以便为您关注的每个meta_key表添加案例“evt_date”和“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()' );