简体   繁体   English

编写此查询的更好/更有效的方法

[英]A better / more efficient way to write this query

I am trying to count the number of records in a table. 我正在尝试计算表中的记录数。 The table is called affiliations and only has 4 columns (2 of which are foreign keys) 该表称为从属关系,只有4列(其中2个是外键)

I want to count the number of records where the affiliated column is 0 and the business_id is related to a particular account_email. 我想计算附属列为0且business_id与特定account_email相关的记录数。

I know how to do this query using the IN keyword, but I was wondering if there is a better or more efficient way to do this. 我知道如何使用IN关键字执行此查询,但是我想知道是否有更好或更有效的方法来执行此查询。

This is the IN version of the query: 这是查询的IN版本:

SELECT COUNT(1) FROM affiliations 
WHERE business_id IN (
    SELECT business_id 
    FROM affiliations 
    WHERE account_email = 'address@domain.ext'
) AND affiliated = 0

I understand I could probably replace this with EXISTS: 我知道我可以用EXISTS代替它:

SELECT COUNT(1) FROM affiliations 
WHERE EXISTS (
    SELECT 1 FROM affiliations 
    WHERE account_email = 'address@domain.ext'
) AND affiliated = 0

Would the statement with EXISTS work? 带有EXISTS的语句行得通吗? And as previously asked, is there just a better way to do this? 如前所述,有没有更好的方法呢?

Thanks in advance! 提前致谢!

I'd use exists, but also remember to correlate the subquery to the primary table as below. 我会使用存在的,但也要记住将子查询与主表相关联,如下所示。

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

The first query from the question with IN clause is not equivalent to the second with EXIST . 来自带有IN子句的问题的第一个查询不等同于带有EXIST的第二个查询。

To convert the first query with IN , you must use a dependent subquery: 要使用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

Pay attention to this condition: AND a1.business_id = a2.business_id 请注意以下情况: AND a1.business_id = a2.business_id

The above query is semantically eqivalent to your first query with IN . 上面的查询在语义上等同于您使用IN进行的第一个查询。
Their performance are the same as well, because MySql, during the optimalization phase, converts intenrally a condition of this form: 它们的性能也相同,因为MySql在优化阶段会内部转换以下形式的条件:

outer_expr IN (SELECT inner_expr FROM ... WHERE subquery_where)

into this: 到这个:

EXISTS (SELECT 1 FROM ... WHERE subquery_where AND outer_expr=inner_expr)

See this link for detalis: http://dev.mysql.com/doc/refman/5.0/en/subquery-optimization-with-exists.html 有关详细信息,请参见此链接: http : //dev.mysql.com/doc/refman/5.0/en/subquery-optimization-with-exists.html
Pay speciall attention to discussion about NULL values and how NULL impacts the optimizer. 请特别注意有关NULL值以及NULL如何影响优化器的讨论。

In short - if business_id column is declared as NOT NULL , then MySql is able to optimize these two queries. 简而言之-如果将business_id列声明为NOT NULL ,则MySql可以优化这两个查询。
See final conclusion (at the bottom of the page in this link): 请参阅最终结论(在此链接页面底部):

To help the query optimizer better execute your queries, use these tips: 为了帮助查询优化器更好地执行查询,请使用以下提示:

  • A column must be declared as NOT NULL if it really is. 如果确实是一列,则必须将其声明为NOT NULL。 (This also helps other aspects of the optimizer.) (这也有助于优化程序的其他方面。)

  • If you don't need to distinguish a NULL from FALSE subquery result, you can easily avoid the slow execution path. 如果您不需要将NULL与FALSE子查询结果区分开,则可以轻松避免执行路径缓慢。 Replace a comparison that looks like this: 替换如下所示的比较:

    outer_expr IN (SELECT inner_expr FROM ...) external_expr IN(从...选择inner_expr ...)

    with this expression: 具有以下表达式:

    (outer_expr IS NOT NULL) AND (outer_expr IN (SELECT inner_expr FROM ...)) (outer_expr不为空)和(outer_expr IN(选择FROM的inner_expr ...))

    Then NULL IN (SELECT ...) will never be evaluated because MySQL stops evaluating AND parts as soon as the expression result is clear. 然后,永远不会对NULL IN(SELECT ...)进行求值,因为一旦表达式结果清除,MySQL就会立即停止对AND部件求值。

Use JOIN instead of IN. 使用JOIN代替IN。 IN is terrible for performance if you're trying to match a lot of values 如果您尝试匹配许多值,则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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM