代码之家  ›  专栏  ›  技术社区  ›  littlegreen

在这种情况下,如何避免嵌套的SQL查询?

  •  1
  • littlegreen  · 技术社区  · 15 年前

    我有一个SQL问题,与 this this 问题(但不同)。基本上我想知道如何避免嵌套查询。

    假设我有一大堆工作( jobs )由他们历史上的一家公司执行。这些作业以年、月、位置和属于作业所用工具的代码为特征。另外,我还有一张工具表( tools )将刀具代码转换为刀具描述和有关刀具的进一步数据。现在,他们需要一个网站,在那里他们可以使用下拉框选择年、月、位置和工具,然后将显示匹配的作业。我只想在最后一个下拉列表中填写与之前选择的年、月和位置匹配的相关工具,因此我编写了以下嵌套查询:

    SELECT c.tool_code, t.tool_description
    FROM (
     SELECT DISTINCT j.tool_code
     FROM jobs AS j
     WHERE j.year = ....
            AND j.month = ....
     AND j.location = ....
    ) AS c
    LEFT JOIN tools as t
    ON c.tool_code = t.tool_code
    ORDER BY c.tool_code ASC
    

    我之所以使用这种嵌套查询,是因为它比在完整的数据库上执行联接并从中进行选择快得多。这使我的查询时间大大缩短了。但正如我最近读到的 MySQL nested queries should be avoided at all cost 我想知道我在这个方法上是否错了。我应该以不同的方式重写我的查询吗?如何?

    2 回复  |  直到 15 年前
        1
  •  2
  •   Quassnoi    15 年前

    不,你不应该,你的问题很好。

    只需在上创建索引 jobs (year, month, location, tool_code) tools (tool_code) 以便 INDEX FOR GROUP-BY 可以使用。

    您提供的文章描述了子查询谓词( IN (SELECT ...) )而不是嵌套查询( SELECT FROM (SELECT ...) )

    即使使用子查询,文章也是错误的:尽管 MySQL 无法优化所有子查询,它处理 IN (SELECT …) 谓词很好。

    我不知道作者为什么选择 DISTINCT 在这里:

    SELECT  id, name, price
    FROM    widgets
    WHERE   id IN
            (
            SELECT  DISTINCT widgetId
            FROM    widgetOrders
            )
    

    他们为什么认为这有助于提高绩效,但鉴于此 widgetID 被索引, MySQL 将转换此查询:

    SELECT  id, name, price
    FROM    widgets
    WHERE   id IN
            (
            SELECT  widgetId
            FROM    widgetOrders
            )
    

    变成一个 index_subquery

    本质上,这就像 EXISTS 子句:内部子查询将每执行一次 widgets 添加了附加谓词的行:

    SELECT  NULL
    FROM    widgetOrders
    WHERE   widgetId = widgets.id
    

    在第一场比赛中停下来 widgetOrders .

    此查询:

    SELECT  DISTINCT w.id,w.name,w.price
    FROM    widgets w
    INNER JOIN
            widgetOrders o
    ON      w.id = o.widgetId
    

    必须使用 temporary 为了消除重复,速度会慢得多。

        2
  •  2
  •   Peter Lang    15 年前

    您可以使用 GROUP BY ,但如果子查询性能更好,请保留它。

    你为什么用 LEFT JOIN 而不是 JOIN 加入 tools ?