Mysql 为什么这个SQL内部连接可以工作,而它不能';T

Mysql 为什么这个SQL内部连接可以工作,而它不能';T,mysql,sql,wordpress,Mysql,Sql,Wordpress,我对SQL还是相当陌生,我很难理解为什么这些查询中的一个功能正常,而另一个功能不正常。这是因为我试图去做。对我来说,这是一个很好的建议,但在我的网站上似乎不起作用。以下是问题 这是WordPress生成的标准SQL(按预期工作): 这是@kalengi的过滤器将多个内部联接合并为一个后的SQL(返回0个结果): 谁能解释一下第二个不起作用吗?看起来您的WHERE子句中有一个条件,它在pmta.meta_键和pmta.meta_值列中同时查找两个值: .... ( pmta.meta_key =

我对SQL还是相当陌生,我很难理解为什么这些查询中的一个功能正常,而另一个功能不正常。这是因为我试图去做。对我来说,这是一个很好的建议,但在我的网站上似乎不起作用。以下是问题

这是WordPress生成的标准SQL(按预期工作):

这是@kalengi的过滤器将多个内部联接合并为一个后的SQL(返回0个结果):


谁能解释一下第二个不起作用吗?

看起来您的
WHERE
子句中有一个条件,它在
pmta.meta_键
pmta.meta_值
列中同时查找两个值:

....
( 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' )
....
一列不能在同一行中有两个不同的值,因此此测试将返回FALSE,因此不会返回任何行

如果重写原始查询以将联接条件分组到
ON
子句中,则可以看到第二个查询无法工作的原因:

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
如果只想加入表一次,请尝试以下操作:

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
两个内部连接:

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
条件,结果将由两行组成,其中第一行(
wp_postmeta
)满足一个条件:

   (wp_postmeta.meta_key = '_visibility' AND CAST(wp_postmeta.meta_value AS CHAR) IN ('visible','catalog'))
   (mt1.meta_key = '_stock_status' AND CAST(mt1.meta_value AS CHAR) = 'instock')
第二种情况完全不同:

   (wp_postmeta.meta_key = '_visibility' AND CAST(wp_postmeta.meta_value AS CHAR) IN ('visible','catalog'))
   (mt1.meta_key = '_stock_status' AND CAST(mt1.meta_value AS CHAR) = 'instock')
通过将所有内容组合成一个
内部联接
,您将寻找一个同时满足这两个条件的行。显然没有

如果您查看“brilliant solution”,您将看到“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' )
)

请提供提交此查询时收到的错误。不会生成错误。问题只是没有返回正确的结果。第一个查询返回数据库中与条件匹配的4行。第二个返回0。感谢您的解释。我是这么想的,但我不确定。您知道有什么方法可以重写第一个查询以减少内部联接,或者这是不可能的?您的问题表明您没有看到我关于将一些AND更改为ORs的更新。谢谢,我确实看到了更新,但我觉得该查询检索到的信息与第一个查询检索到的信息不一样。我需要
“U可见性”
为“可见/目录”,而
“U库存状态”
为“库存”。修改后的版本不会返回两种情况都有但不一定都有的结果吗?@RichardSitze我同意你的解释。每行wp_postmeta均针对所有条件进行测试,如果使用and而不是OR,则应始终失败。我提供的关于链接问题的解决方案适用于我的案例,因为我需要的是或。感谢您的解释。第一个查询的问题是,当您有一个更复杂的版本(如我提到的问题所示)时,多个内部联接会对性能造成巨大的影响。所以,我试图找到一种方法,在没有这么多内部连接的情况下得到结果。我理解。我更新了我的答案,添加了另一个你可以使用的选项。哇,真是太酷了。我不认为你可以在内部连接语句中这样做。但我很难理解为什么这样做有效。我看到您将join中的多个子句(以前的WHERE子句)与OR组合在一起。我认为这会失败,因为我希望所有的条件都是真实的。但是,它正如预期的那样工作。你能帮我理解为什么吗?我不能肯定MySQL中是否如此(我主要使用Oracle),但我相信在
WHERE
ON
子句中定义表之间链接的语句会导致相同的查询执行计划。您希望某些值的组合为true,但并非所有值都为true,这就是为什么需要
。如果您只是比较
wp\u postETA.meta\u key
值,您可以说
…和wp\u postETA.meta\u key in(“'u visibility','u stock\u status')…
,而不需要
。好的,这是有意义的。我开始更了解这一点。因为我需要所有的条件都是真的,所以我几乎被多个内部连接卡住了。