仅使用 WHERE 子句,我们可以看到一些问题:
WHERE wp_term_taxonomy.term_id IN (SELECT term_id FROM wp_terms
WHERE slug='academia' OR slug='law' OR slug='policy')
AND wp_term_taxonomy.term_id IN (SELECT term_id FROM wp_terms
WHERE slug='full-time' OR slug='part-time')
AND wp_term_taxonomy.term_id IN (SELECT term_id FROM wp_terms
WHERE slug='early-career')
在这里,我们有单列 ( wp_term_taxonomy.term_id
),它必须与学术、法律或政策之一的术语 ID 同时相同(可能是 3 个不同的值),并且与全职或兼职之一的术语 ID 相同(可能是 2 个不同的值,并且与之前的 3 个值中的每一个都不同)并且也与 Early-Career 的术语 ID 相同(一个值,但与之前的 5 个值不同。因此,单个术语 ID 必须一次是 3 个不同的值,它无法管理它。
您可能需要wp_term_taxonomy
使用 3 个不同的别名多次加入该表。
WHERE wtt1.term_id IN (SELECT term_id FROM wp_terms
WHERE slug='academia' OR slug='law' OR slug='policy')
AND wtt2.term_id IN (SELECT term_id FROM wp_terms
WHERE slug='full-time' OR slug='part-time')
AND wtt3.term_id IN (SELECT term_id FROM wp_terms
WHERE slug='early-career')
我使用的 3 个别名是wtt1
,wtt2
和wtt3
. 它们将列在 JOIN 条件中。
让我们看一下选择列表和 FROM 子句
SELECT * FROM $wpdb->posts
LEFT JOIN $wpdb->postmeta ON($wpdb->posts.ID = $wpdb->postmeta.post_id)
LEFT JOIN $wpdb->term_relationships ON($wpdb->posts.ID = $wpdb->term_relationships.object_id)
LEFT JOIN $wpdb->term_taxonomy ON($wpdb->term_relationships.term_taxonomy_id = $wpdb->term_taxonomy.term_taxonomy_id)
LEFT JOIN $wpdb->terms ON($wpdb->terms.term_id = $wpdb->term_taxonomy.term_id)
现在让我们解开一些 PHP 材料,留下常规 SQL:
SELECT *
FROM wp_posts AS p
LEFT JOIN wp_postmeta AS pm ON p.ID = pm.post_id
LEFT JOIN wp_term_relationships AS tr ON p.ID = tr.object_id
LEFT JOIN wp_term_taxonomy AS tt ON tr.term_taxonomy_id = tt.term_taxonomy_id
LEFT JOIN wp_terms AS tm ON tm.term_id = tt.term_id
您可能不希望这里有任何左连接;您不想看到不符合条件的帖子,但使用 LEFT JOIN 将意味着在这一部分中选择了许多帖子(尽管所有行随后都被已经讨论过的损坏的 WHERE 条件丢弃)。
一个帖子可能有多个术语关系条目。我们想要一个至少包含三个任期关系条目的帖子:一个用于学术界/法律/政策三人组,一个用于全职/兼职二人组,以及早期职业。
SELECT *
FROM wp_posts AS p
JOIN wp_postmeta AS pm ON p.ID = pm.Post_ID
JOIN (SELECT t1.Object_ID
FROM wp_term_relationships AS tr
JOIN wp_term_taxonomy AS tt ON tr.term_taxonomy_id = tt.term_taxonomy_id
JOIN wp_terms AS tm ON tm.term_id = tt.term_id
WHERE tm.slug IN ('academia', 'law', 'policy')
) AS t1 ON p.ID = t1.Object_ID
JOIN (SELECT t1.Object_ID
FROM wp_term_relationships AS tr
JOIN wp_term_taxonomy AS tt ON tr.term_taxonomy_id = tt.term_taxonomy_id
JOIN wp_terms AS tm ON tm.term_id = tt.term_id
WHERE tm.slug IN ('full-time', 'part-time')
) AS t2 ON p.ID = t2.Object_ID
JOIN (SELECT t1.Object_ID
FROM wp_term_relationships AS tr
JOIN wp_term_taxonomy AS tt ON tr.term_taxonomy_id = tt.term_taxonomy_id
JOIN wp_terms AS tm ON tm.term_id = tt.term_id
WHERE tm.slug = 'early-career')
) AS t3 ON p.ID = t3.Object_ID
我认为这可能会奏效——但现在已经很晚了,我可能会完全脱离困境。这当然不是一个简单的查询。
假设我的基本 SQL 是正确的,您只需将表名替换为 PHP 表示法即可:
SELECT *
FROM $wpdb->posts AS p
JOIN $wpdb->postmeta AS pm ON p.ID = pm.Post_ID
JOIN (SELECT t1.Object_ID
FROM $wpdb->term_relationships AS tr
JOIN $wpdb->term_taxonomy AS tt ON tr.term_taxonomy_id = tt.term_taxonomy_id
JOIN $wpdb->terms AS tm ON tm.term_id = tt.term_id
WHERE tm.slug IN ('academia', 'law', 'policy')
) AS t1 ON p.ID = t1.Object_ID
JOIN (SELECT t1.Object_ID
FROM $wpdb->term_relationships AS tr
JOIN $wpdb->term_taxonomy AS tt ON tr.term_taxonomy_id = tt.term_taxonomy_id
JOIN $wpdb->terms AS tm ON tm.term_id = tt.term_id
WHERE tm.slug IN ('full-time', 'part-time')
) AS t2 ON p.ID = t2.Object_ID
JOIN (SELECT t1.Object_ID
FROM $wpdb->term_relationships AS tr
JOIN $wpdb->term_taxonomy AS tt ON tr.term_taxonomy_id = tt.term_taxonomy_id
JOIN $wpdb->terms AS tm ON tm.term_id = tt.term_id
WHERE tm.slug = 'early-career')
) AS t3 ON p.ID = t3.Object_ID
您没有说正在使用哪个 DBMS,但它很可能是 MySQL。如果您使用的是 Oracle,则必须将 AS 排除在表别名之外。标准 SQL 和大多数其他 SQL DBMS 都可以使用 AS 作为表别名。请注意$wpdb->
符号的使用如何受到表别名的限制;它使代码更容易阅读(尽管它仍然不容易阅读)。
错误修复和问题解决
未经测试的代码通常有错误;这与任何其他未经测试的代码没有什么不同。
第一个测试步骤是单独运行 FROM 子句中的子查询。这立即表明他们不应该引用t1.Object_ID
;tr.Object_ID
在每种情况下都应该如此。在“早期职业”之后还有一个无关紧要的右括号。一旦我有一个可以运行(子)查询的测试数据库,这些错误就很容易被发现。
SELECT *
FROM wp_posts AS p
JOIN wp_postmeta AS pm ON p.ID = pm.Post_ID
JOIN (SELECT tr.Object_ID
FROM wp_term_relationships AS tr
JOIN wp_term_taxonomy AS tt ON tr.term_taxonomy_id = tt.term_taxonomy_id
JOIN wp_terms AS tm ON tm.term_id = tt.term_id
WHERE tm.slug IN ('academia', 'law', 'policy')
) AS t1 ON p.ID = t1.Object_ID
JOIN (SELECT tr.Object_ID
FROM wp_term_relationships AS tr
JOIN wp_term_taxonomy AS tt ON tr.term_taxonomy_id = tt.term_taxonomy_id
JOIN wp_terms AS tm ON tm.term_id = tt.term_id
WHERE tm.slug IN ('full-time', 'part-time')
) AS t2 ON p.ID = t2.Object_ID
JOIN (SELECT tr.Object_ID
FROM wp_term_relationships AS tr
JOIN wp_term_taxonomy AS tt ON tr.term_taxonomy_id = tt.term_taxonomy_id
JOIN wp_terms AS tm ON tm.term_id = tt.term_id
WHERE tm.slug = 'early-career'
) AS t3 ON p.ID = t3.Object_ID
通过这些修复,查询运行并生成了数据行。您可能会合理地决定您想要结果中的三个子查询中的 slug。您将子查询更改为 return tr.Object_ID, tm.slug
。例如,查询的这个变体:
SELECT p.ID, t1.slug_1, t2.slug_2, t3.slug_3, pm.meta_key
FROM wp_posts AS p
JOIN wp_postmeta AS pm ON p.ID = pm.Post_ID
JOIN (SELECT tr.Object_ID, tm.slug AS slug_1
FROM wp_term_relationships AS tr
JOIN wp_term_taxonomy AS tt ON tr.term_taxonomy_id = tt.term_taxonomy_id
JOIN wp_terms AS tm ON tm.term_id = tt.term_id
WHERE tm.slug IN ('academia', 'law', 'policy')
) AS t1 ON p.ID = t1.Object_ID
JOIN (SELECT tr.Object_ID, tm.slug AS slug_2
FROM wp_term_relationships AS tr
JOIN wp_term_taxonomy AS tt ON tr.term_taxonomy_id = tt.term_taxonomy_id
JOIN wp_terms AS tm ON tm.term_id = tt.term_id
WHERE tm.slug IN ('full-time', 'part-time')
) AS t2 ON p.ID = t2.Object_ID
JOIN (SELECT tr.Object_ID, tm.slug AS slug_3
FROM wp_term_relationships AS tr
JOIN wp_term_taxonomy AS tt ON tr.term_taxonomy_id = tt.term_taxonomy_id
JOIN wp_terms AS tm ON tm.term_id = tt.term_id
WHERE tm.slug = 'early-career'
) AS t3 ON p.ID = t3.Object_ID;
在一些测试数据上产生了以下结果:
1575 policy full-time early-career date_legible
1575 policy full-time early-career date_timestamp
1575 policy full-time early-career longitude
1575 policy full-time early-career date_normal
1575 policy full-time early-career url
1575 policy full-time early-career _su_rich_snippet_type
1575 policy full-time early-career _edit_last
1575 policy full-time early-career expiration-date
1575 policy full-time early-career organization
1575 policy full-time early-career latitude
1575 policy full-time early-career location
1575 policy full-time early-career _edit_lock
这表明至少有一篇文章 (ID = 1575) 具有您需要的三个特征,但这也表明您将不得不更巧妙地处理 PostMeta 数据。结果表明 PostMeta 是一个 EAV(实体-属性-值)模型。这将需要仔细处理以提取给定帖子的有用信息(例如纬度和经度)。实际上,您将需要一个(可能是外部的)连接用于您想要检查的每个单独的元属性。
例如,要收集帖子的纬度和经度(如果有),您需要编写:
SELECT p.ID, t1.slug_1, t2.slug_2, t3.slug_3, p1.latitude, p2.longitude
FROM wp_posts AS p
LEFT JOIN
(SELECT Post_ID, Meta_Key AS m1_key, Meta_Value AS latitude
FROM wp_postmeta
WHERE Meta_Key = 'latitude'
) AS p1 ON p.ID = p1.Post_ID
LEFT JOIN
(SELECT Post_ID, Meta_Key AS m2_key, Meta_Value AS longitude
FROM wp_postmeta
WHERE Meta_Key = 'longitude'
) AS p2 ON p.ID = p2.Post_ID
JOIN (SELECT tr.Object_ID, tm.slug AS slug_1
FROM wp_term_relationships AS tr
JOIN wp_term_taxonomy AS tt ON tr.term_taxonomy_id = tt.term_taxonomy_id
JOIN wp_terms AS tm ON tm.term_id = tt.term_id
WHERE tm.slug IN ('academia', 'law', 'policy')
) AS t1 ON p.ID = t1.Object_ID
JOIN (SELECT tr.Object_ID, tm.slug AS slug_2
FROM wp_term_relationships AS tr
JOIN wp_term_taxonomy AS tt ON tr.term_taxonomy_id = tt.term_taxonomy_id
JOIN wp_terms AS tm ON tm.term_id = tt.term_id
WHERE tm.slug IN ('full-time', 'part-time')
) AS t2 ON p.ID = t2.Object_ID
JOIN (SELECT tr.Object_ID, tm.slug AS slug_3
FROM wp_term_relationships AS tr
JOIN wp_term_taxonomy AS tt ON tr.term_taxonomy_id = tt.term_taxonomy_id
JOIN wp_terms AS tm ON tm.term_id = tt.term_id
WHERE tm.slug = 'early-career'
) AS t3 ON p.ID = t3.Object_ID;
产生:
1575 policy full-time early-career -33.8210366 151.1887557
等等。