mysql - 使用 IN 根据多个元键/值对获取 WP 帖子

标签 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
    )
);

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

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

但是,如果我 var_dump( $posts ); 到页面上,上面的查询将返回 null 值,所以我认为 in 部分会导致某种排序也许与第一个元键/值规则冲突?

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

例如:

  • 帖子 1 的 post_type 为 book,元键/值对为 book_genrefiction 并具有“category”和 440 元键/值对,因此使用上述查询应包含

  • Post 2 的 post_type 为 book,元键/值对为 book_genrefiction 并具有“category”和 323 元键/值对,因此使用上述查询不应包含其中。

最佳答案

您需要加入 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

这里有两个 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 来完成此操作。

关于mysql - 使用 IN 根据多个元键/值对获取 WP 帖子,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58259885/

相关文章:

javascript - Onchange 下拉选择

php - 从 mySQL 数据库中回显一个整数

php - 通过 SQL 检索库存中所有没有图像的 WooCommerce 产品

jquery - 联系表格 7 3.5.2 升级 WordPress 3.6 后不发送电子邮件

php - 从 MySQL 生成表到 PDF(使用 PHP)

php - 在 Laravel 更新查询中使用数组

mysql按总和和最好成绩排名

php - 前端多文件上传 WordPress

php - 如何在 Wordpress 中使用 PHP 使用 XSLT 转换 XML

php - 使用 ACF 编号字段作为 WooCommerce 自定义产品类型的价格