在 MySQL 中用连接替换子查询

Posted

技术标签:

【中文标题】在 MySQL 中用连接替换子查询【英文标题】:Replacing Subqueries with Joins in MySQL 【发布时间】:2013-02-12 00:39:49 【问题描述】:

我有以下疑问:

SELECT PKID, QuestionText, Type 
FROM Questions 
WHERE PKID IN (
    SELECT FirstQuestion 
    FROM Batch 
    WHERE BatchNumber IN (
        SELECT BatchNumber 
        FROM User 
        WHERE RandomString = '$key'
    )
)

我听说子查询效率低下,而联接是首选。但是,我找不到任何解释如何将 3 层以上的子查询转换为连接表示法的内容,也无法理解它。

谁能解释一下怎么做?

【问题讨论】:

如果你发布你的表格结构会很好 【参考方案1】:
SELECT  DISTINCT a.*
FROM    Questions a
        INNER JOIN Batch b
            ON a.PKID = b.FirstQuestion
        INNER JOIN User c
            ON b.BatchNumber = c.BatchNumber
WHERE   c.RandomString = '$key'

之所以指定DISTINCT,是因为可能存在与其他表上的多行匹配的行,导致结果出现重复记录。但由于您只对表 Questions 上的记录感兴趣,因此 DISTINCT 关键字就足够了。

如需进一步了解联接,请访问以下链接:

Visual Representation of SQL Joins

【讨论】:

谢谢JW。这是一种享受。我只会说我将a.* 更改为a.PKID, a.QuestionText, a.Type :) 漫长的一天,我的头完全没有了,但这让我免于绝望【参考方案2】:

试试:

SELECT q.PKID, q.QuestionText, q.Type 
FROM Questions q
INNER JOIN Batch b ON q.PKID = b.FirstQuestion
INNER JOIN User u ON u.BatchNumber = q.BatchNumber
WHERE u.RandomString = '$key'

【讨论】:

【参考方案3】:
select
    q.pkid,
    q.questiontext,
    q.type
from user u
join batch b
    on u.batchnumber = b.batchnumber
join questions q
    on b.firstquestion = q.pkid
where u.randomstring = '$key'

由于您的WHERE 子句过滤了USER 表,因此从FROM 子句中的那个开始。接下来,向后应用您的联接。

【讨论】:

【参考方案4】:

为了正确执行此操作,您需要在子查询中使用distinct。否则,您可能会在连接版本中增加行数:

SELECT q.PKID, q.QuestionText, q.Type 
FROM Questions q join
     (select distinct FirstQuestion
      from Batch b join user u
           on b.batchnumber = u.batchnumber and
              u.RandomString = '$key'
     ) fq
     on q.pkid = fq.FirstQuestion

至于in还是join版本更好。 . .那要看。在某些情况下,特别是当字段被索引时,in 版本可能没问题。

【讨论】:

以上是关于在 MySQL 中用连接替换子查询的主要内容,如果未能解决你的问题,请参考以下文章

MYSQL基础九--子查询和连接

那个mysql 子查询和连接查询 一般常用哪个 谁效率高些

MySQL--5子查询与连接小结

mysql中,如何向测试人员介绍连接查询和子查询的优劣势?

MySQL进阶 — 联合查询(外连接内连接子连接合并查询)

MySQL进阶 — 联合查询(外连接内连接子连接合并查询)