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

时间:2018-03-27 09:45:46

标签: mysql wordpress

我在格式化查询时遇到一些问题,根据两个元值的值从数据库中获取帖子列表。我正在使用WordPress 4.9.4,我需要使用$wpdb->get_results()正常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
    )
);

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

  • 该帖子在post_type
  • 中有book wp_posts
  • book_genre
  • 中有fiction和meta_value wp_postmeta的meta_key
  • category
  • 中有239, 440和meta_value wp_postmeta的meta_key
  • 将结果限制为xyz
  • 偏移xyz
  • 的结果

但是,如果I null在页面上,上面的查询会返回var_dump( $posts );的值,所以我想这部分是与第一个元键/值规则发生某种冲突,也许?

如果我删除查询的IN部分,它会按预期获得所有内容,减去我想要的类别的过滤。类别ID是一组id,使用PHP implode()转换为逗号分隔的字符串。

例如:

  • 帖子1的post_type为book,其元键/值对为book_genrefiction,并且具有元键/值对“类别”和440因此 使用上述查询。

  • 帖子2的post_type为book,其元键/值对为book_genrefiction,并且具有元键/值对“类别”和323因此 不应 使用上述查询。

1 个答案:

答案 0 :(得分: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          |
+---------+------------+----------+----------+-----------+-------------+

因此,每个帖子+元值只有一行。您的查询要求同时存在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

在这里,您有两个已归结为pm1pm2的postmeta表的联合副本(因为它们在查询中无法被称为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做到这一点。