0

私はまだ SQL にかなり慣れていないため、これらのクエリの 1 つが適切に機能し、1 つが機能しない理由を理解するのに苦労しています。これは、複雑で遅いクエリを最適化しようとした結果です。@kalengiは私にとって素晴らしい解決策のように見えるものを提案しましたが、私のサイトではうまくいかないようです。ここにクエリがあります。

これは、WordPress が生成する標準の SQL です (これは期待どおりに機能しています)。

SELECT SQL_CALC_FOUND_ROWS wp_posts.ID
FROM wp_posts 
INNER JOIN wp_postmeta ON (wp_posts.ID = wp_postmeta.post_id)
INNER JOIN wp_postmeta AS mt1 ON (wp_posts.ID = mt1.post_id)
WHERE 1=1 
AND wp_posts.post_type = 'product'
AND (wp_posts.post_status = 'publish')
AND (
   (wp_postmeta.meta_key = '_visibility' AND CAST(wp_postmeta.meta_value AS CHAR) IN ('visible','catalog'))
   AND  (mt1.meta_key = '_stock_status' AND CAST(mt1.meta_value AS CHAR) = 'instock')
)
GROUP BY wp_posts.ID
ORDER BY wp_posts.menu_order,wp_posts.post_title asc
LIMIT 0, 10

これは、@kalengi のフィルターが処理して複数の INNER JOIN を 1 つに結合した後の SQL です (これは 0 の結果を返します)。

SELECT SQL_CALC_FOUND_ROWS wp_posts.ID
FROM wp_posts 
INNER JOIN wp_postmeta AS pmta ON (wp_posts.ID = pmta.post_id) 
WHERE 1=1 
AND wp_posts.post_type = 'product'
AND ( wp_posts.post_status = 'publish' )
AND (
  ( pmta.meta_key = '_visibility' AND CAST(pmta.meta_value AS CHAR) IN ( 'visible','catalog' ) )
  AND ( pmta.meta_key = '_stock_status' AND CAST(pmta.meta_value AS CHAR) = 'instock' )
)
GROUP BY wp_posts.ID
ORDER BY wp_posts.menu_order,wp_posts.post_title asc
LIMIT 0, 10

2番目のものがうまくいかない理由を誰か説明できますか?

4

2 に答える 2

1

句に、列と列WHEREで同時に2つの値を検索する条件があるようです。pmta.meta_keypmta.meta_value

....
( pmta.meta_key = '_visibility' AND CAST(pmta.meta_value AS CHAR) IN ('visible','catalog' ) )
AND ( pmta.meta_key = '_stock_status' AND CAST(pmta.meta_value AS CHAR) = 'instock' )
....

1つの列が同じ行に2つの異なる値を持つことはできないため、このテストはFALSEを返し、その結果、行は返されません。

元のクエリを書き直して結合条件をON句にグループ化すると、2番目のクエリが機能しない理由がわかります。

SELECT 
    SQL_CALC_FOUND_ROWS wp_posts.ID
FROM 
    wp_posts 
    INNER JOIN wp_postmeta 
        ON wp_posts.ID = wp_postmeta.post_id
        AND wp_postmeta.meta_key = '_visibility' 
        AND CAST(wp_postmeta.meta_value AS CHAR) IN ('visible','catalog')
    INNER JOIN wp_postmeta AS mt1 
        ON wp_posts.ID = mt1.post_id
        AND mt1.meta_key = '_stock_status' 
        AND CAST(mt1.meta_value AS CHAR) = 'instock'
WHERE 
    1=1 
    AND wp_posts.post_type = 'product'
    AND wp_posts.post_status = 'publish'
GROUP BY 
    wp_posts.ID
ORDER BY 
    wp_posts.menu_order,
    wp_posts.post_title asc
LIMIT 0, 10

テーブルに1回だけ参加する場合は、次のようにしてみてください。

SELECT 
    SQL_CALC_FOUND_ROWS wp_posts.ID
FROM 
    wp_posts 
    INNER JOIN wp_postmeta 
        ON wp_posts.ID = wp_postmeta.post_id
        AND (
            wp_postmeta.meta_key = '_visibility' 
            AND CAST(wp_postmeta.meta_value AS CHAR) IN ('visible','catalog')
        ) OR (
            wp_postmeta.meta_key = '_stock_status' 
            AND CAST(wp_postmeta.meta_value AS CHAR) = 'instock'
        )
WHERE 
    1=1 
    AND wp_posts.post_type = 'product'
    AND wp_posts.post_status = 'publish'
GROUP BY 
    wp_posts.ID
ORDER BY 
    wp_posts.menu_order,
    wp_posts.post_title asc
LIMIT 0, 10
于 2013-03-15T18:23:15.280 に答える
1

2 つの内部結合:

INNER JOIN wp_postmeta ON (wp_posts.ID = wp_postmeta.post_id)
INNER JOIN wp_postmeta AS mt1 ON (wp_posts.ID = mt1.post_id)

2 つのデータセットを表します (たまたま「同じ」)。

条件WHEREを指定すると、結果は最初の ( wp_postmeta) が 1 つの条件を満たす2 つの行のセットになります。

   (wp_postmeta.meta_key = '_visibility' AND CAST(wp_postmeta.meta_value AS CHAR) IN ('visible','catalog'))

そして、2番目は完全に異なる条件を満たしています:

   (mt1.meta_key = '_stock_status' AND CAST(mt1.meta_value AS CHAR) = 'instock')

すべてを 1 つINNER JOINに結合することで、代わりに両方の条件に一致する 1 つの ROW を探しています。どうやら一つもないようです。

「素晴らしい解決策」を確認すると、セマンティクスを維持するために「AND」が「OR」に変更されていることがわかります。

AND (
  ( pmta.meta_key = '_visibility' AND CAST(pmta.meta_value AS CHAR) IN ( 'visible','catalog' ) )
  OR ( pmta.meta_key = '_stock_status' AND CAST(pmta.meta_value AS CHAR) = 'instock' )
)
于 2013-03-15T18:28:18.023 に答える