【问题标题】:Wordpress : Sql select posts with all related metaWordpress:Sql 选择包含所有相关元数据的帖子
【发布时间】:2017-06-18 14:40:41
【问题描述】:

我需要获取包含所有相关元数据的一系列帖子。 所以它应该是这样的:

post
  postfields from post table : [
                               'title' =>...
                               'content'=>...
                               etc....
                               ]
  array of values from meta : [
                               [],
                               []
                              ],
 post
   postfields from post table : [
                               'title' =>...
                               'content'=>...
                               etc....
                               ]
   array of values from meta : [
                               [],
                               []
                              ]

我正在尝试做的事情:

SELECT
    *
FROM wp_posts
    INNER JOIN wp_postmeta
    ON wp_posts.ID = wp_postmeta.post_id
    WHERE wp_posts.post_type = 'page'
    GROUP BY wp_posts.ID

但它失败了。

#1055 - Expression #24 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'somedbname.wp_postmeta.meta_id' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by

如何在一个查询中获取包含所有相关元数据的所有帖子?

【问题讨论】:

  • 你能澄清你所说的“失败”是什么意思吗?您是否遇到了 SQL 错误,或者您获得的结果与您的预期不同?
  • 左连接而不是内连接怎么样?
  • 可能已经有插件可以做到这一点
  • 左连接不能做到这一点。我仍然需要一个帖子数组,每个数组元素都应该包含帖子和所有相关的元数据。在单个查询中。

标签: php mysql wordpress


【解决方案1】:

这两个表有几点需要注意。

  1. 帖子和帖子元具有一对多的关系。因此,通过使用GROUP BY wp_posts.ID,您会将结果限制为具有第一个相关帖子元记录的单个帖子(并且任何其他相关的帖子元数据都不会显示)。
  2. 通过使用INNER JOIN wp_postmeta,查询将不会返回任何没有帖子元的帖子。

您可以使用的一种设计模式是执行查询GROUP BY wp_posts.ID(这将导致单个帖子有多个行,因为每行将包含相同的帖子 ID 但不同的帖子元)并在 PHP 中重构您的数组。与执行多个查询相比,PHP 中的这种循环相当高效。如果需要,您还可以将结果缓存在 transient 中。

举个例子来说明,你应该能够像这样执行你的查询:

global $wpdb;
$results = $wpdb->get_results( "SELECT * FROM wp_posts LEFT JOIN wp_postmeta ON wp_posts.ID = wp_postmeta.post_id WHERE wp_posts.post_type = 'page' ORDER BY wp_posts.ID" );

if ( ! empty( $results ) ) {
    $previous_id = 0;
    $structured_results = array();
    foreach ( $results as $post ) {
        if ( $previous_id !== $post->ID ) {
            $structured_results[ $post->ID ] = array(
                'ID' => $post->ID,
                'post_author' => $post->post_author,
                'post_date' => $post->post_date,
                'post_title' => $post->post_title,
                // etc for all other columns in wp_posts
                'post_meta' => array(
                    $post->meta_id => array(
                        'meta_key' => $post->meta_key,
                        'meta_value' => $post->meta_value,
                    ),
                ),
            );
        } else {
            $structured_results[ $post->ID ]['post_meta'][ $post->meta_id ] = array(
                'meta_key' => $post->meta_key,
                'meta_value' => $post->meta_value,
            );

        }
        $previous_id = $post->ID;
    }
}

这将为您提供一个名为structured_results 的结果数组。数组的每个元素将是一个单独的帖子(它的关键是帖子 ID)。每个元素将包含来自wp_posts 的所有列。此外,每个元素都有一个名为post_meta 的键,它是一个所有张贴元记录的数组。

几点说明:

  • 这是LEFT JOIN,因此它将包含没有帖子元的帖子(如果您只想要带有元的帖子,请使用INNER JOIN)。
  • 上面代码中我没有从wp_posts填写所有列,所以你可以添加额外的列(例如post_content等)。

【讨论】:

  • 是的,我明白了。那么,有什么办法可以避免限制呢?我只需要发布数据和所有相关的元数据
  • @Alicelf 我用一些应该适合你的示例代码更新了我的答案
  • 谢谢,但这不是我问的。是的,我可以在 php 中重新组合它,但我需要在一个查询中获取它。所以查询应该返回帖子数组,每个数组元素应该包含帖子数据和所有与这个帖子元相关的内容。就是这样
  • @Alicelf 不幸的是,不可能使用纯 SQL 以您描述的方式构建 一对多 关系。但是,我描述的解决方案仍然执行一个查询。
猜你喜欢
  • 2015-05-10
  • 1970-01-01
  • 2013-11-15
  • 2012-05-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多