代码之家  ›  专栏  ›  技术社区  ›  Brian T Hannan

SQL:像这样的查询是可以的,还是有更有效的方法,比如使用连接?

  •  5
  • Brian T Hannan  · 技术社区  · 15 年前

    我经常发现自己想要编写如下的SQL查询:

    SELECT body 
      FROM node_revisions 
     where vid = (SELECT vid 
                    FROM node 
                   WHERE nid = 4);
    

    我知道有连接和你可以做的事情,但它们似乎使事情变得更复杂。加入是更好的方法吗?它更有效吗?更容易理解?

    8 回复  |  直到 15 年前
        1
  •  7
  •   Oded    15 年前

    连接往往更有效,因为在编写数据库时考虑了集合操作(而连接是集合操作)。

    但是,不同数据库的性能、表的结构、表中的数据量以及查询返回的数据量都会有所不同。

    如果数据量很小,我将使用像您这样的子查询,而不是联接。

    以下是联接的外观:

    SELECT body 
    FROM node_revisions nr
    INNER JOIN node n
      ON nr.vid = n.vid
    WHERE n.nid = 4
    

    我不会使用您发布的查询,因为有可能有多个节点记录具有 nid = 4 会导致失败。

    我会用:

    SELECT body 
    FROM node_revisions 
    WHERE vid IN (SELECT vid 
                 FROM node 
                 WHERE nid = 4);
    

    这是更易读还是更容易理解?在这种情况下,这是个人偏好的问题。

        2
  •  3
  •   Ray    15 年前

    我认为连接更容易理解,而且效率更高。你的案子很简单,所以很可能是个麻烦。以下是我的写作方法:

    SELECT body 
      FROM node_revisions 
        inner join node 
          on (node_revisions.vid = node.vid)
      WHERE node.nid = 4
    
        3
  •  3
  •   Mark Canlas    15 年前

    数据库中与性能相关的问题的答案是 它取决于 我们在操作中缺少细节。不知道你的具体情况…(因此,这些是一般的经验法则)

    连接更好,更容易理解

    • 如果出于某种原因需要多个列键(fishy),可以继续使用join,只需将另一个表达式附加到join条件。
    • 如果将来确实需要联接辅助数据,那么联接框架已经存在了。
    • 它使您更清楚地了解要加入的内容以及应该在哪里实现索引。
    • 使用连接可以使您更好地进行连接,并且更好地考虑连接。
    • 连接明确了什么表在起作用

    书面询问与效率无关。*

    您编写的查询以及实际运行的查询彼此之间几乎没有关系。编写查询有很多种方法,但获取数据的方法却很少,这取决于查询引擎来决定。这主要与索引有关。可以编写四个看起来完全不同但内部执行相同操作的查询。

    (*写一个效率低下的可怕的查询是可能的,但这样做需要一种特殊的疯狂。)

    select
      body
    
    from node_revisions nr
    
    join node n
    on n.vid = nr.vid
    
    where n.nid = 4
    
        4
  •  2
  •   Jordão    15 年前

    加入是有趣的:

    select body 
    from node_revisions nr
    join node n on nr.vid = n.vid
    where n.vid = 4
    

    但是你也可以表达一个没有加入的加入。]

    select body 
    from node_revisions nr, node n
    where n.nid = 4 and nr.vid = n.vid
    

    有趣的是,对于这两个查询,SQL Server给出了一个稍微不同的查询计划,而join有一个聚集索引扫描,“join without a join”有一个聚集索引查找,这表明它是 better 至少在这种情况下!

        5
  •  1
  •   Jeff    15 年前
    select 
         body 
    from node_revisions A 
    where exists (select 'x' 
                  from Node B 
                  Where A.Vid = B.Vid and B.NID=4)
    
        6
  •  1
  •   Otávio Décio    15 年前

    我看不出你写的有什么问题,如果合适的话,一个好的优化器甚至可以把它改成一个连接。

        7
  •  1
  •   Quassnoi    15 年前
    SELECT  body 
    FROM    node_revisions 
    WHERE   vid =
            (
            SELECT  vid 
            FROM    node 
            WHERE   nid = 4
            )
    

    此查询在逻辑上等同于一个join if且only if nid 是一个 PRIMARY KEY 或包含在 UNIQUE 约束。

    否则,查询是不等价的:一个联接总是成功的,而如果有更多的联接,子查询将失败。 1 排在 node 具有 nid = 4 .

    如果 尼德 是一个 主键 ,然后 JOIN 子查询的性能相同。

    如果是连接, 结点 将成为领导

    如果是子查询,子查询将执行一次并转换为 const 在分析阶段。

        8
  •  1
  •   jspcal    15 年前

    最新的mysql 6.x代码将使用 半联接子查询优化 ,使这两个陈述在很大程度上等效:

    http://forge.mysql.com/worklog/task.php?id=3740

    但是,实际上写出来是非常简单的,因为内部连接是默认的连接类型,这样做并不依赖于服务器对其进行优化(因为某些原因,它可能决定不进行优化,也不一定是可移植的)。一切都是平等的,为什么不去:

    select body from node_revisions r, node n where r.vid = n.vid and n.node = 4