如何计算某个meta_key在列中出现的meta_value的次数?

Posted

技术标签:

【中文标题】如何计算某个meta_key在列中出现的meta_value的次数?【英文标题】:How to count how many times a meta_value appears in a column by certain meta_key? 【发布时间】:2016-01-20 06:07:59 【问题描述】:

我正在尝试从 WordPress 的数据库中查询每条记录在我的表中的列上存在多少次并导出该列。我该怎么做?

在导出的 excel 中,我希望 meta_value 中的列带有 meta_key “user_valid”,以及一列中包含该 meta_value 在 mysql 列中存在多少次的计数。

meta_key          meta_value

user_valid        '1, 2, 3'      
user_valid        '1, 2, 1' 
user_valid        '1, 2, 3'

用于导出列 'meta_value' 和我使用的 meta_key 'user_valid':

SELECT meta_value FROM `us_test` WHERE meta_key = 'user_valid'

使用此查询后,我使用 MYSQL 中的导出按钮导出。

我不知道如何查询另一列。

我认为应该是这样的,但我不确定,因为当我使用下一个查询时,它不会返回所有记录:

SELECT meta_value, COUNT( * ) c FROM `us_test` WHERE meta_key = 'user_valid' GROUP BY meta_value

【问题讨论】:

我很困惑......你是否给自己一个“模范”答案的赏金?还是您正在寻找替代方案? @rnevius 我认为 OP 选择了错误的赏金解释。有更好的方法可以做到这一点,所以我认为他需要这些替代方案的答案 【参考方案1】:

这里有两种选择,一种是 Wordpress,另一种是 SQL。

在我开始之前,您永远不应该对数据库名称进行硬编码,问题是,如果您将代码移动到具有不同数据库名称的另一个网站,则需要在所有硬编码查询中更改数据库名称,当您在您正在处理的网站上更改数据库名称时。如果您忘记了这一点,这会让您大吃一惊

您应该始终清理和验证输入数据,以确保可以安全地防止任何恶意代码注入您的网站。 SQL 注入很常见,许多黑客使用 SQL 注入来入侵网站

SQL

SQL 提供的控制较少,因为它的动态性较低。例如,如果您只需要获取某个词的计数,则需要直接更改查询,或者您需要实现某种过滤系统。

正如我所说,永远不要硬编码数据库名称,而是使用 wpdb 类来设置前缀。这将避免未来的问题。另外,正如我所说,您必须进行清理以避免 SQL 注入,在这种情况下,我们将使用 wpdb 类的 prepare 方法来进行清理并防止 SQL 注入。

这里是函数,我在这里和那里评论过它是有意义的:

function get_post_meta_key_count( $key = '', $value = '', $type = 'post', $status = 'publish' ) 

    // Use $wpdb to avoid bugs and errors, do not hardcode db names
    global $wpdb;

    if( empty( $key ) )
        return;


    // Set the default WHERE clause where we return the count of the key regardless of value
    $where = $wpdb->prepare( 
        "
            pm.meta_key = '%s' 
            AND p.post_type = '%s' 
            AND p.post_status = '%s'
        ", 
        $key, 
        $type, 
        $status 
    );

    // If a value is specified, add that to the WHERE clause
    if ( $value ) 
        $where .= $wpdb->prepare( 
            "
                AND pm.meta_value = '%s'
            ", 
            $value 
        );
    

    // Query the db to return the post count according to key and value if value is set
    $count = $wpdb->get_var(
        "
            SELECT count(DISTINCT pm.post_id)
            FROM $wpdb->postmeta pm
            JOIN $wpdb->posts p ON (p.ID = pm.post_id)
            WHERE $where
        "
    );

    return $count;

我在这里所做的是,如果您需要获取特定元键的特定元值的计数,我已经设置了一个参数。

用法

您现在可以使用如下功能:

echo get_post_meta_key_count( 'my_key' ); 用于 meta_key 的帖子计数 my_key 用于默认帖子类型 post 并且仅发布帖子

echo get_post_meta_key_count( 'my_key', '', 'custom_post_type', 'trash' ); 用于 meta_key 的帖子计数 my_key 用于自定义帖子类型 custom_post_type 并且仅垃圾帖子

echo get_post_meta_key_count( 'my_key', 'my_value' ); 用于meta_key my_key 的帖子计数和meta_valuemy_value 用于默认帖子类型post 并且仅发布帖子

WP_Query

如果您正在寻找一种内置方式来执行此操作(这应该始终是您的首选),您可以使用 WP_Query 类来执行此操作。

使用WP_Query 的问题在于,如果使用不当,可能会非常昂贵。许多人因此而避免WP_Query,或者在不知不觉中运行非常昂贵且不必要的查询。因此,我们将寻找一种方法使其与自定义 SQL 查询一样快。

WP_Query 上述自定义 SQL 查询的真正优势在于,您可以通过简单地传入所需的参数来调整查询,WP_Query 将始终负责根据传递参数。

让我们看看优化 WP_Query 以便只返回帖子计数

首先,我们将只查询一个帖子。 WP_Query,默认情况下,无论查询多少帖子(1、100 或所有帖子),WP_Query 都会继续寻找所有与查询匹配的帖子,即使它已经找到并返回了查询的帖子数量。原因是分页。为了正确计算分页,WP_Query 需要知道有多少帖子与查询匹配。

所以WP_Query 在返回查询的帖子数量后继续查看数据库,以计算与查询匹配的所有帖子。这个帖子计数存储在查询的$found_posts 属性中,并且正是这个数字与posts_per_page 一起使用,用于计算将有多少页。

这不适用于get_posts,尽管get_posts 使用WP_Queryget_posts'no_found_rows' => true 传递给 WP_Query,一旦找到查询的帖子数量,就会中断查询。这在法律上破坏了分页,这就是为什么 get_posts 正确分页是如此令人头疼的原因

其次,我们只会查询我们需要查询的单个帖子的ID,而不是完整的WP_Post对象。这节省了查询时间。

让我们看看这个函数:

function get_post_meta_key_count( $key = '', $value = '', $args = [] ) 

    // If the $key value is empty, bail
    if( empty( $key ) )
        return;

    // Set the defaults and override any value set for the specific default
    $args['posts_per_page'] = 1;
    $args['fields']         = 'ids';

    if ( $value ) 
        $args['meta_query'][] = [
            'key'   => $key,
            'value' => $value
        ];
     else 
        $args['meta_query'][] = [
            'key' => $key,
        ];
    
    $q = new WP_Query( $args );

    // Return the post count
    return $q->found_posts;

用法

WP_Query,默认使用post帖子类型和publish作为帖子状态,所以我们不需要为正常发布的帖子设置这个。我在这里包含了第三个参数$args,该参数接受与WP_Query 类相同的参数,因为这些参数都直接传递给WP_Query。因此,您可以在此处添加任何参数以从特定元键或值中获取计数

echo get_post_meta_key_count( 'my_key' ); 用于meta_key 的帖子计数my_key 用于默认帖子类型post 并且仅发布帖子

echo get_post_meta_key_count( 'my_key', 'my_value' ); 用于meta_key my_key 的帖子计数和meta_valuemy_value 用于默认帖子类型post 并且仅发布帖子

echo get_post_meta_key_count( 'my_key', 'my_value', ['post_type'=>'cpt', 'cat'=>1] ); 用于meta_key my_key 的帖子计数和meta_valuemy_value 用于自定义帖子类型cpt 并且仅发布来自类别ID 1 的帖子

meta_key 的性能测试,包含 24 个帖子

SQL -> 1 个查询在 +/- 0.005 秒内

WP_Query -> +/- 0.012 秒内 2 次查询

如您所见,性能存在细微差别,因此WP_Query 方法很容易成为最佳选择,因为它更具动态性,尽管速度稍慢

【讨论】:

【参考方案2】:

所以,我会回答我自己的问题:

我的问题是绝对正确的:

SELECT meta_value, COUNT( * ) c FROM `us_test` WHERE meta_key = 'user_valid' GROUP BY meta_value

【讨论】:

以上是关于如何计算某个meta_key在列中出现的meta_value的次数?的主要内容,如果未能解决你的问题,请参考以下文章

如何计算某些值在 SQL 表中出现的次数并在列中返回该数字?

计算 PySpark SQL Join 中每个不同值在列中出现的次数

如果存在另一个 meta_key,则插入 meta_key

Python:如果字符串出现在列中,则删除行

Wordpress WP_Query 与 meta_key 的多个 meta_values

如何从 meta_key wordpress 中删除超链接