wordpress memberships-获取一个计划的所有活动成员,这些成员对一个特定的元键有一个非空值还检索其他元数据

im9ewurl  于 2021-06-20  发布在  Mysql
关注(0)|答案(1)|浏览(313)

我正在创建一个谷歌Map为我所有的活动wp成员标记。首先,我需要查询数据库以获取特定成员计划(传递给函数)的所有活动(和/或免费)成员,但它们对于自定义meta\u键也必须具有非空值 affiliate_location . 有一个可供我的会员使用的前端表单,他们可以通过在表单中输入自己的位置(和其他详细信息)来选择加入Map,并将信息保存为用户元。如果他们没有输入他们的位置,他们的meta\u键将有一个空的meta\u值 affiliate_location .
我已经完成了以上的工作。我的功能可以检查用户是否是活动/免费会员,然后检查他们是否有非空的 affiliate_location meta\u值,并返回这些用户的列表,其中包括其用户标识、显示名称和 affiliate_location meta_键和meta_值(meta_值是我将用来在googleMap上放置它们的标记)。
我现在要做的是,如果用户通过上述测试,就返回额外的用户元数据。如果它们是活动成员并输入了位置,那么我还想返回(在同一查询中)以下元键的元值: affiliate_name , affiliate_email , affiliate_website , affiliate_phone_number .
在@loictheaztec对这个问题的回答的帮助下,我尝试了下面的sql查询,调整sql以检查 affiliate_location 元价值。
我尝试为需要返回的其他元键/值对别名用户元表。你可以在最后一页看到这个 LEFT JOIN ... usermeta AS um1... 行,然后列出 um1.meta_key 在第一个表达式中,最后包括条件 AND um1.meta_key = 'affiliate_name' ,但结果只有一个 meta_key 还有一个 meta_value 财产。我不知道如何返回每个匹配用户所需的附加元数据。非常感谢您的帮助!

// List of Active Users for a Membership Plan
function get_active_members_for_membership( $membership_slug )
{
    global $wpdb;

    // Getting all User IDs and data for a membership plan
    return $wpdb->get_results( "

        SELECT DISTINCT um.user_id, u.display_name, um.meta_key, um.meta_value, um1.meta_key, um1.meta_value

        FROM {$wpdb->prefix}posts AS p
            LEFT JOIN {$wpdb->prefix}posts AS p2 ON p2.ID = p.post_parent
            LEFT JOIN {$wpdb->prefix}users AS u ON u.id = p.post_author
            LEFT JOIN {$wpdb->prefix}usermeta AS um ON u.id = um.user_id
            LEFT JOIN {$wpdb->prefix}usermeta AS um1 ON u.id = um1.user_id

        WHERE p.post_type = 'wc_user_membership'
            AND p.post_status IN ('wcm-active', 'wcm-complimentary')
            AND p2.post_type = 'wc_membership_plan'
            AND p2.post_name LIKE '$membership_slug'
            AND um.meta_key = 'affiliate_location'
            AND um.meta_value <> ''
            AND um1.meta_key = 'affiliate_name'
            -- AND um.meta_key = 'affiliate_email'
            -- AND um.meta_key = 'affiliate_website'
            -- AND um.meta_key = 'affiliate_phone_number'
    " );
}

以下是我从上述尝试中得到的结果:

Array
(
    [0] => stdClass Object
        (
            [user_id] => 1
            [display_name] => Colin
            [meta_key] => affiliate_name
            [meta_value] => fake affiliate name 1
        )

    [1] => stdClass Object
        (
            [user_id] => 925
            [display_name] => Hello
            [meta_key] => affiliate_name
            [meta_value] => fake affiliate name 2
        )
)

在本例中,如您所见,结果包括 affiliate_name 元键/值。这只是我想要的一部分。如果我移除 um1.meta_key, um1.meta_value 从第一个sql表达式,然后我得到位置元键/值。
基本上,对于所有匹配的用户(“活动”成员,他们有商店 affiliate_location 数据)我还需要返回他们的姓名,电子邮件,网站和电话号码,在同一查询。否则,我将不得不运行一个查询来获取所有匹配的用户,然后使用他们的userid值来运行数百个单独的查询,以便收集他们的所有分支数据。有没有办法在一个查询中获得所有这些数据?
非常感谢您的帮助!
更新:
我已经实现了@edward的解决方案。他提出了两个解决方案,一个是标准的join子查询,另一个是更高级的outer apply,但是我发现我的mysql数据库不接受outer apply语法,所以我选择实现第一个解决方案,并做了一些更正(有一个输入错误) websiteweb_site )以及主where子句末尾的附加条件。以下是我尝试的:

SELECT DISTINCT user_meta.user_id, u.display_name, user_meta.loc_key, user_meta.loc_value, user_meta.name_key, user_meta.name_value, user_meta.email_key, user_meta.email_value, user_meta.website_key, user_meta.website_value, user_meta.phone_key, user_meta.phone_value

FROM {$wpdb->prefix}posts AS p
    LEFT JOIN {$wpdb->prefix}posts AS p2 ON p2.ID = p.post_parent
    LEFT JOIN {$wpdb->prefix}users AS u ON u.id = p.post_author
    LEFT JOIN
    (
        SELECT
            loc.user_id,
            loc.meta_key AS loc_key,
            loc.meta_value AS loc_value,
            name.meta_key AS name_key,
            name.meta_value AS name_value,
            email.meta_key AS email_key,
            email.meta_value AS email_value,
            website.meta_key AS website_key,
            website.meta_value AS website_value,
            phone.meta_key  AS phone_key,
            phone.meta_value  AS phone_value

        FROM {$wpdb->prefix}usermeta AS loc
            LEFT JOIN {$wpdb->prefix}usermeta AS name
                ON loc.user_id = name.user_id
                AND name.meta_key = 'affiliate_name'
            LEFT JOIN {$wpdb->prefix}usermeta AS email
                ON loc.user_id = email.user_id
                AND email.meta_key = 'affiliate_email'
            LEFT JOIN {$wpdb->prefix}usermeta AS website
                ON loc.user_id = website.user_id
                AND website.meta_key = 'affiliate_website'
            LEFT JOIN {$wpdb->prefix}usermeta AS phone
                ON loc.user_id = phone.user_id
                AND phone.meta_key = 'affiliate_phone_number'

        WHERE loc.meta_key = 'affiliate_location'
            AND loc.meta_value <> ''

    )  AS user_meta ON user_meta.user_id = u.id

WHERE p.post_type = 'wc_user_membership'
    AND p.post_status IN ('wcm-active', 'wcm-complimentary')
    AND p2.post_type = 'wc_membership_plan'
    AND p2.post_name LIKE '$membership_slug'
    AND user_meta.loc_value <> ''

这个解决方案正是我想要的!没有决赛 AND user_meta.loc_value <> '' 条件下,返回的数组包含所有“活动”用户,即使这些用户为空 affiliate_location 价值观。通过添加最终条件,这些用户被过滤掉。
非常感谢您的帮助@edward,非常感谢!我学到了很多。干杯!

4ioopgfo

4ioopgfo1#

我想我找到你的问题了。这个 um1.meta_value 他回来了 NULL 因为你没有过滤 um1. 基于非空的 affiliate_location 像你这样的元值规则 um. .
特别是 WHERE 你没有做你想让他们做的事。

WHERE ...
            AND um.meta_key = 'affiliate_location'
            AND um.meta_value <> ''
            AND um1.meta_key = 'affiliate_name'

因为在你的 FROM 子句,您正在使用两个 LEFT OUTER JOIN 的。
我不知道你的数据结构,但添加了一些东西到 WHERE 这样可能有用:

AND um1.user_id = um.user_id -- this is what will force um1. records to match um. records
  AND um1.meta_value <> '' -- this should be removed unless everyone with a location also has an affilicate_name

这有帮助吗?
07/12
因此,针对你的评论,我将在这里展开我的回答。这个 LEFT JOINS 你所做的确实是从 usermeta ,但重要的是sql将它们视为两个独立的对象。
这很重要,因为 WHERE 声明 AND um.meta_key = affiliate_location 不会影响 usermeta AS um1 返回的列 SELECT ... um1.meta_key , um1.meta_value ... .
它不是在做你期望它做的事情。
为了 um1 要仅返回感兴趣的列,需要进行筛选 um 就像你已经做过的,然后显式地强制 um1.id 匹配 um.id .
你也可以试试这个。

FROM ..
LEFT JOIN (
  SELECT um.user_id , um.meta_key, um1.meta_value
  FROM usermeta as um 
  INNER JOIN usermeta as um1 
    ON um.user_id = um1.user_id 
  WHERE 
       um.meta_key = 'affiliate_location'
   AND um.meta_value <> '' 
   AND um1.meta_key = 'affiliate_name') AS usermeta 
ON usermeta.user_id = u.id

我重新修改了您原来的查询一点,这应该有希望返回您所要求的。

SELECT DISTINCT 
            user_meta.user_id
        ,   u.display_name
        ,   user_meta.loc_key
        ,   user_meta.loc_value
        ,   user_meta.name_key
        ,   user_meta.name_value
        ,   user_meta.email_key
        ,   user_meta.email_value
        ,   user_meta.website_key
        ,   user_meta.website_value
        ,   user_meta.phone_key
        ,   user_meta.phone_value
    FROM {$wpdb->prefix}posts AS p
    LEFT JOIN {$wpdb->prefix}posts AS p2 ON p2.ID = p.post_parent
    LEFT JOIN {$wpdb->prefix}users AS u ON u.id = p.post_author
    LEFT JOIN ( 
        SELECT 
                loc.user_id
            ,   loc.meta_key AS loc_key
            ,   loc.meta_value AS loc_value
            ,   name.meta_key AS name_key
            ,   name.meta_value AS name_value
            ,   email.meta_key AS email_key
            ,   email.meta_value AS email_value
            ,   website.meta_key AS website_key
            ,   website.meta_value AS website_value
            ,   phone.meta_key  AS phone_key
            ,   phone.meta_value  AS phone_value
        FROM {$wpdb->prefix}usermeta AS loc 
        LEFT JOIN {$wpdb->prefix}usermeta AS name 
            ON loc.id = name.user_id
            AND name.meta_key = 'affiliate_name'
        LEFT JOIN {$wpdb->prefix}usermeta AS email 
            ON loc.id = email.user_id
            AND email.meta_key = 'affiliate_email'
        LEFT JOIN {$wpdb->prefix}usermeta AS website
            ON loc.id = website.user_id
            AND web_site.meta_key = 'affiliate_website'
        LEFT JOIN {$wpdb->prefix}usermeta AS phone
            ON loc.id = phone.user_id
            AND phone.meta_key = 'affiliate_phone_number'
        WHERE loc.meta_key = 'affiliate_location'
        AND loc.meta_value <> ''
    )  AS user_meta
    ON user_meta.user_id = u.id 
WHERE p.post_type = 'wc_user_membership'
    AND p.post_status IN ('wcm-active', 'wcm-complimentary')
    AND p2.post_type = 'wc_membership_plan'
    AND p2.post_name LIKE '$membership_slug'
    AND user_meta.loc_value <> ''

这可能是相当低效的,因为所有的 LEFT JOINS .
07/13-上述解决方案 LEFT OUTER JOIN 为…工作 mySQL . 如果有人在尝试类似的东西 SQLServer ,那么他们的运气会更好 OUTER APPLY 所以我把它留在这个答案里。

SELECT DISTINCT 
            um.user_id
        ,   u.display_name
        ,   meta_data.meta_key
        ,   meta_data.meta_value
    FROM {$wpdb->prefix}posts AS p
    LEFT JOIN {$wpdb->prefix}posts AS p2 ON p2.ID = p.post_parent
    LEFT JOIN {$wpdb->prefix}users AS u ON u.id = p.post_author
    LEFT JOIN {$wpdb->prefix}usermeta as um ON um.user_id = u.id 
    OUTER APPLY ( 
            SELECT meta_key , meta_value
            FROM usermeta as um1 
            WHERE um1.meta_key IN ('affiliate_name', 'affiliate_phone_number' , 'affiliate_email' , 'affiliate_website')
            AND um1.user_id = um.user_id
            ORDER BY um1.meta_key ASC 
        ) as meta_data 
    WHERE p.post_type = 'wc_user_membership'
    AND p.post_status IN ('wcm-active', 'wcm-complimentary')
    AND p2.post_type = 'wc_membership_plan'
    AND p2.post_name LIKE '$membership_slug'
    AND um.meta_key = 'affiliate_location'
    AND um.meta_value <> ''

相关问题