php - Wordpress Memberships - 获取计划中对特定元键具有非空值的所有活动成员。还检索其他元数据
问题描述
我正在为我所有活跃的 WP Memberships 成员创建一个带有标记的谷歌地图。首先,我需要查询数据库以获取特定会员计划(传递给函数)的所有 ACTIVE(和/或 COMPLIMENTARY)成员,但它们还必须具有自定义 meta_key 的非空值affiliate_location
。我的成员可以使用一个前端表单,他们可以通过在表单中输入他们的位置(和其他详细信息)来选择加入地图,并将信息保存为用户元数据。如果他们没有输入他们的位置,他们的 meta_key 将有一个空的 meta_value affiliate_location
。
我已经完成了上述工作。我的函数可以检查用户是否是活跃/免费会员,然后检查他们是否有非空的affiliate_location
meta_value,并返回这些用户的列表,其中包括他们的 user_id、display_name 以及affiliate_location
meta_key 和 meta_value (meta_value 是我用来将他们的标记放在谷歌地图上的)。
我现在想要完成的是,如果他们通过上述测试,则返回额外的用户元数据。如果他们是活动成员并输入了位置,那么我还想(在同一个查询中)返回以下元键的元值: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
数据的“活跃”成员),我还需要在同一个查询中返回他们的姓名、电子邮件、网站和电话号码。否则,我将不得不运行一个查询来获取所有匹配的用户,然后使用他们的 User_ID 值来运行数百个单独的查询,以收集他们所有的附属数据。有没有办法在一个查询中获取所有数据?
非常感谢您的帮助!
更新:
我已经实施了@Edward 的解决方案。他提出了 2 个解决方案,一个带有标准的 JOIN 子查询,另一个带有更高级的 OUTER APPLY,但是我发现我的 MySQL 数据库不接受 OUTER APPLY 语法,所以我选择实现第一个解决方案,并进行了一些更正(与website
vs有一个错字web_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 非常感谢!我学到了很多。干杯!
解决方案
我想我找到了你的问题。um1.meta_value
正在返回,NULL
因为您没有像 for 那样基于元值规则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 <> ''
推荐阅读
- debugging - 无法使用 org-link-open-from-string 打开链接,因为 (file-name-directory (buffer-file-name)) 似乎返回 nil
- node.js - 使用 Express 覆盖所有响应标头
- ios - Xcode 尝试在未从模拟器卸载的情况下运行应用程序时显示错误(多配置文件)
- latex - 使用 gnuplot,如何获取具有画布大小的 PDF,包括文本?
- javascript - JavaScript 中的函数是如何实现固有异步的
- json - 使用 powershell 编辑 Json
- python - Python 日志记录失败
- python - 根据 NumPy 中的非标准化对数概率从集合中采样
- python - 网页抓取时如何登录网站
- python - Python 中的粗体注释。相当于 Python 中的 MATLAB '%%'