首页 文章

使用IN获取基于多个元键/值对的WP帖子

提问于
浏览
0

我'm having some trouble formatting my query to fetch a list of posts from the database based on the value of two meta values. I'm使用WordPress 4.9.4我需要使用带参数的 $wpdb->get_results()not 正常的 get_posts() 函数调用 .

这是我到目前为止,但如果我尝试在MySQL查询中包含 IN 部分,它不会返回任何内容,但它应该至少返回一个帖子 .

global $wpdb;

$posts = $wpdb->get_results(
    $wpdb->prepare(
        'SELECT ' . $wpdb->prefix . 'posts.*, ' . $wpdb->prefix . 'postmeta.* FROM ' . $wpdb->prefix . 'posts, ' . $wpdb->prefix . 'postmeta WHERE ' . $wpdb->prefix . 'posts.post_type = %s AND ' . $wpdb->prefix . 'postmeta.post_id = ' . $wpdb->prefix . 'posts.ID AND (' . $wpdb->prefix . 'postmeta.meta_key = %s AND ' . $wpdb->prefix . 'postmeta.meta_value = %s) AND (' . $wpdb->prefix . 'postmeta.meta_key = %s AND ' . $wpdb->prefix . 'postmeta.meta_value IN (%s)) ORDER BY ' . $wpdb->prefix . 'posts.post_title ASC LIMIT %d OFFSET %d',
        'book',
        'book_genre',
        $genre,
        'category',
        '239, 440',
        $limit,
        $offset
    )
);

以上查询应该获取所有帖子:

  • 帖子 book book wp_posts

  • wp_postmeta 中有 book_genre 的meta_key和 fiction 的meta_value

  • wp_postmeta 中有 category 的meta_key和 239, 440 的meta_value

  • 限制结果为 xyz
    _289_偏移结果 xyz

但是,上面的查询返回值为 null ,如果我 var_dump( $posts ); 到页面上,所以我想这可能会导致与第一个元键/值规则发生某种冲突?

如果我删除了查询的 IN 部分,它会按预期获得所有内容,减去当然类别的过滤,即'd like. The category ids are an array of ids that are converted into a comma-separated string using PHP' s implode() .

例如:

  • 发布 1 的post_type为 book ,具有 book_genrefiction 的元键/值对,并且具有'category'和 440 的元键/值对,因此使用上述查询包含 should .

  • 发布 2 的post_type为 book ,具有 book_genrefiction 的元键/值对,并且具有'category'和 323 的元键/值对,因此使用上述查询包含 should not .

1 回答

  • 1

    您需要两次加入 post_meta 表 . 这是一些数据库理论 .

    当您连接表时,理论上临时表包含第一个表中的所有项目以及第二个表中的所有项目的创建和过滤 . 因此,例如,如果您每个帖子只有1个元项目,并且您有3个帖子,那么您就拥有了

    +-------+----------+
    |post_id|post_title|
    +-------+----------+
    |   1   | 'Post 1' |
    |   2   | 'Post 2' |
    |   3   | 'Post 3' |
    +-------+----------+
    

    +-------+----------+----------+------------+
    |meta_id| post_id  | meta_key | meta_value |
    +-------+----------+----------+------------+
    |   10  | 1        |  k1      | v1         |
    |   11  | 2        |  k1      | v2         |
    |   12  | 3        |  k1      | v3         |
    +-------+----------+----------+------------+
    

    而“理论”临时联合表是:

    +---------+------------+----------+----------+-----------+-------------+
    |p.post_id|p.post_title|pm.meta_id|pm.post_id|pm.meta_key|pm.meta_value|
    +---------+------------+----------+----------+-----------+-------------+
    |   1     | 'Post 1'   |   10     | 1        |  k1       | v1          |
    |   1     | 'Post 1'   |   11     | 2        |  k1       | v2          |
    |   1     | 'Post 1'   |   12     | 3        |  k1       | v3          |
    |   2     | 'Post 2'   |   10     | 1        |  k1       | v1          |
    |   2     | 'Post 2'   |   11     | 2        |  k1       | v2          |
    |   2     | 'Post 2'   |   12     | 3        |  k1       | v3          |
    |   3     | 'Post 3'   |   10     | 1        |  k1       | v1          |
    |   3     | 'Post 3'   |   11     | 2        |  k1       | v2          |
    |   3     | 'Post 3'   |   12     | 3        |  k1       | v3          |
    +---------+------------+----------+----------+-----------+-------------+
    

    然后你说:WHERE p.id = pm.post_id

    这会将临时表过滤为:

    +---------+------------+----------+----------+-----------+-------------+
    |p.post_id|p.post_title|pm.meta_id|pm.post_id|pm.meta_key|pm.meta_value|
    +---------+------------+----------+----------+-----------+-------------+
    |   1     | 'Post 1'   |   10     | 1        |  k1       | v1          |
    |   2     | 'Post 2'   |   11     | 2        |  k1       | v2          |
    |   3     | 'Post 3'   |   12     | 3        |  k1       | v3          |
    +---------+------------+----------+----------+-----------+-------------+
    

    因此,每个post meta值只有一行 . 您的查询要求包含 meta_key = category 和meta_key = book_genre`的行不存在 .

    所以你需要一个在TWICE中加入 postmeta 表的表 .

    您可以通过在加入表时对表进行别名来执行此操作 . 请原谅我简化:

    SELECT wp_posts.*, pm1.*, pm2.*
    FROM
      wp_posts
      wp_postmeta as pm1
      wp_postmeta as pm2
    WHERE pm1.post_id = wp_posts.ID
      AND pm2.post_id = wp_posts.ID
      AND ...etc
    

    在这里你有两个联合的postmeta表副本,别名为 pm1pm2 (因为它们在查询中不能被称为 wp_postmeta .

    然后你可以要求:

    AND pm1.meta_key = 'category'
    AND pm1.meta_value = X
    AND pm2.meta_key = 'book_genre'
    AND pm2.meta_key IN (123,456)
    

    希望你可以将其余部分拼接在一起 .

    如果你想走这条路,我也认为你可以用WP_Query做到这一点 .

相关问题