2013-03-22 32 views
0

我正在查詢wordpress posts帖子中的一些帖子,並通過多次加入postmeta表獲取多個元值。我對帖子欄和元值也有很多條件。查詢似乎正在工作,但我很好奇,如果我已經把條件放在正確的地方。比較以下查詢,這些查詢將最有效/最有效地獲得帖子ID及其相關元數據?Mysql多個連接到一個表具有不同的條件 - 他們去哪裏?

這一個:

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

可能重複的[SQL JOIN在哪裏放置WHERE條件?](http://stackoverflow.com/questions/15483808/sql-join-where-to-place-the-where-condition)第二個是不正確,請參閱我提供的鏈接中的原因。 – Sebas 2013-03-22 19:00:52

+0

相關,是的,大多是重複的。一般來說,最好將盡可能多的相關條件放入'JOIN'條件中,特別是在處理某種外連接時。相信我,未來的維護者會感謝你。並且可能是你的優化器。 – 2013-03-22 19:58:53

+0

哈哈,男人,我發誓我第一次上下尋找。似乎我在搜索查詢中包含了太多細節。 – technosis 2013-03-22 20:41:58

回答

0

有bewteen你的兩個查詢的差異。

第一個查詢將返回帖子的值,而不管匹配的metakey值的數量是多少(至少對於「b」值不是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 - 聚合應該大致相同,但使用較少的連接。

+0

非常好,謝謝你的解釋。所以如果我只想要所有3個元值的結果,我會使用查詢#2?使所有連接innner連接在查詢#1中具有相同的效果? – technosis 2013-03-22 20:40:38

+0

@technosis。 。 。如果你想要所有三個,那麼我建議改變連接到內部連接並使用任一查詢。不要使用'left join'並依賴where子句來撤銷它 - 這會使查詢混淆。 – 2013-03-22 20:41:51

+0

對,有道理。謝謝! – technosis 2013-03-22 21:42:37

相關問題