Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/68.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 连接与子查询_Sql_Mysql_Subquery_Join - Fatal编程技术网

Sql 连接与子查询

Sql 连接与子查询,sql,mysql,subquery,join,Sql,Mysql,Subquery,Join,我是一个老派的MySQL用户,总是喜欢JOIN而不是sub-query。但是现在每个人都使用子查询,我讨厌它;我不知道为什么 我缺乏理论知识来判断是否存在差异。子查询是否与连接一样好,因此无需担心?子查询是解决“从a获取事实,以从B获取事实为条件”形式问题的逻辑正确方法。在这种情况下,在子查询中使用B比使用联接更有逻辑意义。从实际意义上讲,它也更安全,因为你不必因为与B的多次匹配而对从a获得重复的事实持谨慎态度 然而,实际上,答案通常取决于性能。一些优化程序在给定联接与子查询时会吸取柠檬,而另一

我是一个老派的MySQL用户,总是喜欢
JOIN
而不是sub-query。但是现在每个人都使用子查询,我讨厌它;我不知道为什么


我缺乏理论知识来判断是否存在差异。子查询是否与连接一样好,因此无需担心?

子查询是解决“从a获取事实,以从B获取事实为条件”形式问题的逻辑正确方法。在这种情况下,在子查询中使用B比使用联接更有逻辑意义。从实际意义上讲,它也更安全,因为你不必因为与B的多次匹配而对从a获得重复的事实持谨慎态度

然而,实际上,答案通常取决于性能。一些优化程序在给定联接与子查询时会吸取柠檬,而另一些优化程序则会以另一种方式吸取柠檬,这是特定于优化程序、特定于DBMS版本和特定于查询的


从历史上看,显式连接通常是成功的,因此公认的观点是连接更好,但乐观主义者总是越来越好,因此我更倾向于以逻辑一致的方式首先编写查询,如果性能限制允许,则重新构造。子查询通常用于将单行作为原子值返回,尽管它们可能用于将值与多行中的IN关键字进行比较。它们几乎可以出现在SQL语句中任何有意义的点上,包括目标列表、WHERE子句等等。一个简单的子查询可以用作搜索条件。例如,在一对表之间:

SELECT title 
FROM books 
WHERE author_id = (
    SELECT id 
    FROM authors 
    WHERE last_name = 'Bar' AND first_name = 'Foo'
);
请注意,对子查询的结果使用普通值运算符只需要返回一个字段。如果您对检查一组其他值中是否存在单个值感兴趣,请使用:

SELECT title 
FROM books 
WHERE author_id IN (
    SELECT id FROM authors WHERE last_name ~ '^[A-E]'
);
这显然不同于左连接,在左连接中,即使连接条件在表B中找不到任何匹配的记录,也只想连接表a和表B中的内容,等等


如果您只是担心速度,那么您必须检查您的数据库并编写一个好的查询,看看性能是否有显著差异。

在大多数情况下,
JOIN
s比子查询快,而且子查询很少更快

JOIN
s中,RDBMS可以创建一个更适合您的查询的执行计划,并且可以预测应该加载哪些数据以进行处理并节省时间,这与子查询不同,子查询将运行所有查询并加载其所有数据以进行处理


子查询的好处是它们比
JOIN
s更具可读性:这就是为什么大多数新SQL用户更喜欢它们;这是最简单的方法;但是说到性能,连接在大多数情况下都会更好,即使它们也不难阅读。

使用EXPLAIN查看数据库如何对数据执行查询。这个答案中有一个巨大的“视情况而定”


PostgreSQL可以将子查询重写为联接,或者在认为其中一个比另一个快时将联接重写为子查询。这完全取决于数据、索引、相关性、数据量、查询等。

首先,要比较这两种情况,您应该将查询与子查询区分开来:

  • 一类子查询,总是使用连接编写相应的等价查询
  • 不能使用联接重写的一类子查询
  • 对于第一类查询,一个好的RDBMS会将连接和子查询视为等价的,并会生成相同的查询计划

    现在连mysql都这么做了

    尽管如此,有时情况并非如此,但这并不意味着连接将永远获胜——我有过在mysql中使用子查询来提高性能的案例。(例如,如果mysql planner无法正确估计成本,并且如果planner没有看到连接变量和子查询变量相同,那么子查询可以通过强制特定路径来超越连接)

    结论是,如果您想确定哪一个查询的性能更好,您应该测试您的查询的联接和子查询变体


    对于第二个类比较没有意义,因为这些查询不能使用连接重写,在这些情况下,子查询是执行所需任务的自然方式,您不应歧视它们。

    在旧Mambo CMS的非常大的数据库上运行:

    SELECT id, alias
    FROM
      mos_categories
    WHERE
      id IN (
        SELECT
          DISTINCT catid
        FROM mos_content
      );
    
    0秒

    SELECT
      DISTINCT mos_content.catid,
      mos_categories.alias
    FROM
      mos_content, mos_categories
    WHERE
      mos_content.catid = mos_categories.id;
    
    约3秒

    解释表明,他们检查的行数完全相同,但一行需要3秒钟,一行几乎是即时的。这个故事的寓意是什么?如果性能很重要(什么时候不是?),请尝试多种方法,看看哪种方法最快

    而且

    SELECT
      DISTINCT mos_categories.id,
      mos_categories.alias
    FROM
      mos_content, mos_categories
    WHERE
      mos_content.catid = mos_categories.id;
    
    0秒

    SELECT
      DISTINCT mos_content.catid,
      mos_categories.alias
    FROM
      mos_content, mos_categories
    WHERE
      mos_content.catid = mos_categories.id;
    
    同样,相同的结果,相同数量的行被检查。我的猜测是,DISTINCT mos_content.catid比DISTINCT mos_categories.id需要更长的时间来计算。

    许多包含子查询的Transact-SQL语句也可以表示为联接。其他问题只能通过子查询提出。在Transact-SQL中,包含子查询的语句与不包含子查询的语义等效版本之间通常没有性能差异。但是,在某些必须检查存在性的情况下,联接会产生更好的性能。否则,必须为外部查询的每个结果处理嵌套查询,以确保消除重复项。在这种情况下,联接方法将产生更好的结果

    所以如果你需要像

    select * from t1 where exists select * from t2 where t2.parent=t1.id
    
    尝试改用join。在其他情况下,这没有什么区别

    我说:为子查询创建函数可以消除clutter问题,并允许您实现子查询的附加逻辑。因此,我建议尽可能为子查询创建函数

    代码混乱是一个大问题,业界一直在努力避免它
    +----+--------------------+----------+--------+-----------------------------------------------------+--------------+---------+-------------------------------------------------+------+--------------------------+
    | id | select_type        | table    | type   | possible_keys                                       | key          | key_len | ref                                             | rows | Extra                    |
    +----+--------------------+----------+--------+-----------------------------------------------------+--------------+---------+-------------------------------------------------+------+--------------------------+
    |  1 | PRIMARY            | vrl      | index  | PRIMARY                                             | moved_date   | 8       | NULL                                            |  200 | Using where              |
    |  1 | PRIMARY            | l        | eq_ref | PRIMARY,status,ispublic,idx_lookup,is_public_status | PRIMARY      | 4       | ranker.vrl.list_id                              |    1 | Using where              |
    |  1 | PRIMARY            | vrlih    | eq_ref | PRIMARY                                             | PRIMARY      | 9       | ranker.vrl.list_id,ranker.vrl.ontology_id,const |    1 | Using where              |
    |  1 | PRIMARY            | lbs      | eq_ref | PRIMARY,idx_list_burial_state,burial_score          | PRIMARY      | 4       | ranker.vrl.list_id                              |    1 | Using where              |
    |  4 | DEPENDENT SUBQUERY | list_tag | ref    | list_tag_key,list_id,tag_id                         | list_tag_key | 9       | ranker.l.list_id,const                          |    1 | Using where; Using index |
    |  3 | DEPENDENT SUBQUERY | list_tag | ref    | list_tag_key,list_id,tag_id                         | list_tag_key | 9       | ranker.l.list_id,const                          |    1 | Using where; Using index |
    |  2 | DEPENDENT SUBQUERY | list_tag | ref    | list_tag_key,list_id,tag_id                         | list_tag_key | 9       | ranker.l.list_id,const                          |    1 | Using where; Using index |
    +----+--------------------+----------+--------+-----------------------------------------------------+--------------+---------+-------------------------------------------------+------+--------------------------+
    
    EXPLAIN SELECT vrl.list_id,vrl.ontology_id,vrl.position,l.name AS list_name, vrlih.position AS previous_position, vrl.moved_date 
    FROM `vote-ranked-listory` vrl 
    INNER JOIN lists l ON l.list_id = vrl.list_id 
    INNER JOIN `vote-ranked-list-item-history` vrlih ON vrl.list_id = vrlih.list_id AND vrl.ontology_id=vrlih.ontology_id AND vrlih.type='PREVIOUS_POSITION' 
    INNER JOIN list_burial_state lbs ON lbs.list_id = vrl.list_id AND lbs.burial_score < 0.5 
    LEFT JOIN list_tag lt1 ON lt1.list_id = vrl.list_id AND lt1.tag_id = 43 
    LEFT JOIN list_tag lt2 ON lt2.list_id = vrl.list_id AND lt2.tag_id = 55 
    INNER JOIN list_tag lt3 ON lt3.list_id = vrl.list_id AND lt3.tag_id = 246403 
    WHERE vrl.position <= 15 AND l.status='ACTIVE' AND l.is_public=1 AND vrl.ontology_id < 1000000000 
    AND lt1.list_id IS NULL AND lt2.tag_id IS NULL 
    ORDER BY vrl.moved_date DESC LIMIT 200;
    
    +----+-------------+-------+--------+-----------------------------------------------------+--------------+---------+---------------------------------------------+------+----------------------------------------------+
    | id | select_type | table | type   | possible_keys                                       | key          | key_len | ref                                         | rows | Extra                                        |
    +----+-------------+-------+--------+-----------------------------------------------------+--------------+---------+---------------------------------------------+------+----------------------------------------------+
    |  1 | SIMPLE      | lt3   | ref    | list_tag_key,list_id,tag_id                         | tag_id       | 5       | const                                       | 2386 | Using where; Using temporary; Using filesort |
    |  1 | SIMPLE      | l     | eq_ref | PRIMARY,status,ispublic,idx_lookup,is_public_status | PRIMARY      | 4       | ranker.lt3.list_id                          |    1 | Using where                                  |
    |  1 | SIMPLE      | vrlih | ref    | PRIMARY                                             | PRIMARY      | 4       | ranker.lt3.list_id                          |  103 | Using where                                  |
    |  1 | SIMPLE      | vrl   | ref    | PRIMARY                                             | PRIMARY      | 8       | ranker.lt3.list_id,ranker.vrlih.ontology_id |   65 | Using where                                  |
    |  1 | SIMPLE      | lt1   | ref    | list_tag_key,list_id,tag_id                         | list_tag_key | 9       | ranker.lt3.list_id,const                    |    1 | Using where; Using index; Not exists         |
    |  1 | SIMPLE      | lbs   | eq_ref | PRIMARY,idx_list_burial_state,burial_score          | PRIMARY      | 4       | ranker.vrl.list_id                          |    1 | Using where                                  |
    |  1 | SIMPLE      | lt2   | ref    | list_tag_key,list_id,tag_id                         | list_tag_key | 9       | ranker.lt3.list_id,const                    |    1 | Using where; Using index                     |
    +----+-------------+-------+--------+-----------------------------------------------------+--------------+---------+---------------------------------------------+------+----------------------------------------------+
    
    AND (SELECT list_id FROM list_tag WHERE list_id=l.list_id AND tag_id=246403) IS NOT NULL  
    
    INNER JOIN list_tag lt3 ON lt3.list_id = vrl.list_id AND lt3.tag_id = 246403
    
    SELECT titles, price
    FROM Books, Orders
    WHERE price = 
    (SELECT MIN(price)
     FROM Orders) AND (Books.ID=Orders.ID);
    
    SELECT MIN(price)
         FROM Orders;
    -----------------
    2.99
    
    SELECT titles, price
    FROM Books b
    INNER JOIN  Orders o
    ON b.ID = o.ID
    WHERE o.price = 2.99;
    
    +------+--------+------+--------+
    | sID  | sName  | GPA  | sizeHS |
    +------+--------+------+--------+
    |  123 | Amy    |  3.9 |   1000 |
    |  234 | Bob    |  3.6 |   1500 |
    |  345 | Craig  |  3.5 |    500 |
    |  456 | Doris  |  3.9 |   1000 |
    |  567 | Edward |  2.9 |   2000 |
    |  678 | Fay    |  3.8 |    200 |
    |  789 | Gary   |  3.4 |    800 |
    |  987 | Helen  |  3.7 |    800 |
    |  876 | Irene  |  3.9 |    400 |
    |  765 | Jay    |  2.9 |   1500 |
    |  654 | Amy    |  3.9 |   1000 |
    |  543 | Craig  |  3.4 |   2000 |
    +------+--------+------+--------+
    
    +------+----------+----------------+----------+
    | sID  | cName    | major          | decision |
    +------+----------+----------------+----------+
    |  123 | Stanford | CS             | Y        |
    |  123 | Stanford | EE             | N        |
    |  123 | Berkeley | CS             | Y        |
    |  123 | Cornell  | EE             | Y        |
    |  234 | Berkeley | biology        | N        |
    |  345 | MIT      | bioengineering | Y        |
    |  345 | Cornell  | bioengineering | N        |
    |  345 | Cornell  | CS             | Y        |
    |  345 | Cornell  | EE             | N        |
    |  678 | Stanford | history        | Y        |
    |  987 | Stanford | CS             | Y        |
    |  987 | Berkeley | CS             | Y        |
    |  876 | Stanford | CS             | N        |
    |  876 | MIT      | biology        | Y        |
    |  876 | MIT      | marine biology | N        |
    |  765 | Stanford | history        | Y        |
    |  765 | Cornell  | history        | N        |
    |  765 | Cornell  | psychology     | Y        |
    |  543 | MIT      | CS             | N        |
    +------+----------+----------------+----------+
    
    select GPA from Student where sID in (select sID from Apply where major = 'CS');
    
    +------+
    | GPA  |
    +------+
    |  3.9 |
    |  3.5 |
    |  3.7 |
    |  3.9 |
    |  3.4 |
    +------+
    
    select avg(GPA) from Student where sID in (select sID from Apply where major = 'CS');
    
    +--------------------+
    | avg(GPA)           |
    +--------------------+
    | 3.6800000000000006 |
    +--------------------+
    
    select GPA from Student, Apply where Student.sID = Apply.sID and Apply.major = 'CS';
    
    +------+
    | GPA  |
    +------+
    |  3.9 |
    |  3.9 |
    |  3.5 |
    |  3.7 |
    |  3.7 |
    |  3.9 |
    |  3.4 |
    +------+
    
    select avg(GPA) from Student, Apply where Student.sID = Apply.sID and Apply.major = 'CS';
    
    +-------------------+
    | avg(GPA)          |
    +-------------------+
    | 3.714285714285714 |
    +-------------------+
    
    SELECT * 
    FROM crv.workorder_details wd 
    inner join  crv.workorder wr on wr.workorder_id = wd.workorder_id;
    
    select * 
    from crv.workorder_details 
    where workorder_id in (select workorder_id from crv.workorder)
    
    SELECT moo, (SELECT roger FROM wilco WHERE moo = me) AS bar FROM foo
    
    SELECT moo FROM foo WHERE bar = (SELECT roger FROM wilco WHERE moo = me)
    
    SELECT moo, bar 
      FROM foo 
        LEFT JOIN (
          SELECT MIN(bar), me FROM wilco GROUP BY me
        ) ON moo = me
    
    SELECT VARIANCE(moo)
      FROM (
        SELECT moo, CONCAT(roger, wilco) AS bar
          FROM foo
          HAVING bar LIKE 'SpaceQ%'
      ) AS temp_foo
      GROUP BY moo
    
         select id,name from table1 a  
       join table2 b on a.name=b.name
       where id='123'
    
     Try,
    
        select id,name from table1 a  
       join table2 b on a.name=b.name and a.id='123'