我正在尝试计算表中的记录数。 该表称为附属关系,只有4列(其中2列是外键)
我想计算附属列为0且business_id与特定account_email相关的记录数。
我知道如何使用IN关键字进行此查询,但我想知道是否有更好或更有效的方法来执行此操作。
这是查询的IN版本:
SELECT COUNT(1) FROM affiliations
WHERE business_id IN (
SELECT business_id
FROM affiliations
WHERE account_email = 'address@domain.ext'
) AND affiliated = 0
我知道我可以用EXISTS取代它:
SELECT COUNT(1) FROM affiliations
WHERE EXISTS (
SELECT 1 FROM affiliations
WHERE account_email = 'address@domain.ext'
) AND affiliated = 0
EXISTS的声明是否有效?如前所述,还有更好的方法吗?
提前致谢!
答案 0 :(得分:1)
我使用exists,但还记得将子查询与主表相关联,如下所示。
SELECT COUNT(1) FROM affiliations a
WHERE exists (
SELECT 1
FROM affiliations a1
WHERE account_email = 'address@domain.ext'
and a1.business_id=a.business_id
) AND affiliated = 0
答案 1 :(得分:0)
带IN
子句的问题中的第一个查询与EXIST
的第二个查询不等效。
要使用IN
转换第一个查询,必须使用从属子查询:
SELECT COUNT(1) FROM affiliations a1
WHERE EXISTS (
SELECT 1 FROM affiliations a2
WHERE account_email = 'address@domain.ext'
AND a1.business_id = a2.business_id
) AND affiliated = 0
注意这种情况:AND a1.business_id = a2.business_id
上述查询在语义上与您使用IN
的第一个查询等效
它们的性能也是一样的,因为在最优化阶段,MySql在意图上转换为这种形式的条件:
outer_expr IN (SELECT inner_expr FROM ... WHERE subquery_where)
进入这个:
EXISTS (SELECT 1 FROM ... WHERE subquery_where AND outer_expr=inner_expr)
请参阅此链接以获取detalis:http://dev.mysql.com/doc/refman/5.0/en/subquery-optimization-with-exists.html
特别注意有关NULL值的讨论以及NULL如何影响优化器。
简而言之 - 如果business_id
列声明为NOT NULL
,则MySql可以优化这两个查询。
查看最终结论(在此链接的页面底部):
为了帮助查询优化器更好地执行查询,请使用以下提示:
如果确实存在,则必须将列声明为NOT NULL。 (这也有助于优化器的其他方面。)
如果您不需要将NULL与FALSE子查询结果区分开来,则可以轻松避免执行路径缓慢。替换看起来像这样的比较:
outer_expr IN(SELECT inner_expr FROM ...)
用这个表达式:
(outer_expr IS NOT NULL)AND(outer_expr IN(SELECT inner_expr FROM ...))
然后永远不会评估NULL IN(SELECT ...),因为只要表达式结果清除,MySQL就会停止评估AND部分。
答案 2 :(得分:-1)
使用JOIN而不是IN。如果你想要匹配很多值,那么IN的表现很糟糕
SELECT COUNT(1)
FROM affiliations AS ABB2
JOIN (SELECT business_id
FROM affiliations
WHERE account_email = 'address@domain.ext') AS ABB1
ON ABB1.business_id = ABB2.business_id
WHERE affiliated = 0