Mysql多个连接到一个具有不同条件的表 - 它们去哪里了?

时间:2013-03-22 18:58:45

标签: mysql sql wordpress

我正在查询wordpress帖子表中的一些帖子,并通过多次加入postmeta表来获取多个元值。对于post列和meta值,我也有很多条件。查询似乎有效但我很好奇,如果我把条件放在正确的位置。比较以下查询,这将最有效/最有效地获得post id及其相关元素?

这一个:

SELECT a.ID as `post_id`, b.meta_value as `metaval1`, c.meta_value as `metaval2`, d.meta_value as `metaval3`
FROM posts AS a
JOIN postmeta AS b ON (b.post_id = a.ID AND b.meta_key = 'metakey1')
LEFT JOIN postmeta as c ON (c.post_id = a.ID AND c.meta_key = 'metakey2')
LEFT JOIN postmeta as d ON (d.post_id = a.ID AND d.meta_key = 'metakey3')
WHERE
    b.meta_value != 10
    AND a.post_status = 'pending'
    AND a.post_date < '2013-03-07 00:00:00'
    AND a.post_type = "post"
ORDER BY a.post_date DESC
LIMIT 100;

或者这个:

SELECT a.ID as `post_id`, b.meta_value as `metaval1`, c.meta_value as `metaval2`, d.meta_value as `metaval3`
FROM posts AS a
JOIN postmeta AS b ON (b.post_id = a.ID)
LEFT JOIN postmeta as c ON (c.post_id = a.ID)
LEFT JOIN postmeta as d ON (d.post_id = a.ID)
WHERE
    b.meta_key = 'metakey1'
    AND b.meta_value != 10
    AND c.meta_key = 'metakey2'
    AND d.meta_key = 'metakey3'
    AND a.post_status = 'pending'
    AND a.post_date < '2013-03-07 00:00:00'
    AND a.post_type = "post"
ORDER BY a.post_date DESC
LIMIT 100;

任何建议都将受到赞赏:)

1 个答案:

答案 0 :(得分:0)

两个问题之间存在差异。

第一个查询将返回帖子的值,无论匹配的metakey值的数量是多少(至少对于&#34; b&#34;值不是10的帖子)。您正在on子句中进行比较,因此left join会处理结果。

第二个查询只会在存在所有三个键时返回值。比较位于where子句中,因此left join生成的不匹配行将被过滤掉。

您更喜欢哪种取决于您想要的结果。两者都应该花费相同的计算量。

如果你想要效率,你也应该尝试:

SELECT p.id,
       max(case when pm.meta_key = 'metakey1' then pm.meta_value end) as metavalue1,
       max(case when pm.meta_key = 'metakey2' then pm.meta_value end) as metavalue2,
       max(case when pm.meta_key = 'metakey3' then pm.meta_value end) as metavalue3
FROM posts p join
     postmeta pm
     on pm.post_id = p.ID
WHERE pm.meta_key in ('metakey1', 'metakey2', 'metakey3') and
      (pm.meta_key <> 'metakey1' or pm.meta_value != 10) and
      p.post_status = 'pending' and
      p.post_date < '2013-03-07 00:00:00' and
      p.post_type = 'post'
group by p.post_date, p.id
ORDER BY p.post_date DESC
LIMIT 100;

这限制了连接数,使用聚合将结果组合在一起。您的原始查询必须扫描结果以执行order by - 聚合应该与工作量相同,但连接次数较少。