将子查询转换为连接

Converting sub-queries to joins

给定以下架构...

我将如何转换以下查询以使用连接(与 MySQL 一起使用)?

SELECT submissions.SubmissionID,
(SELECT data.DataContent FROM data WHERE data.DataFieldName =
    (SELECT forms.FormEmailFieldName FROM forms WHERE forms.FormID = submissions.SubmissionFormID)
AND data.DataSubmissionID = submissions.SubmissionID) AS EmailAddress,
(SELECT data.DataContent FROM data WHERE data.DataFieldName =
    (SELECT forms.FormNameFieldName FROM forms WHERE forms.FormID = submissions.SubmissionFormID)
AND data.DataSubmissionID = submissions.SubmissionID) AS UserName
FROM submissions
WHERE submissions.SubmissionFormID = 4

下面是一些示例数据和我想要的结果...

+--------+--------------------+-------------------+
| forms  |                    |                   |
+--------+--------------------+-------------------+
| FormID | FormEmailFieldName | FormNameFieldName |
| 4      | UserEmailAddress   | UserName          |
| 5      | email              | name              |
+--------+--------------------+-------------------+

+--------------+------------------+
| submissions  |                  |
+--------------+------------------+
| SubmissionID | SubmissionFormID |
| 10           | 4                |
| 11           | 5                |
| 12           | 5                |
+--------------+------------------+

+--------+------------------+------------------+------------------+
|  data  |                  |                  |                  |
+--------+------------------+------------------+------------------+
| DataID | DataSubmissionID | DataFieldName    | DataContent      |
| 1      | 10               | UserEmailAddress | user@example.com |
| 2      | 10               | UserName         | Paul D'Otherone  |
| 3      | 11               | email            | bob@bobs.com     |
| 4      | 11               | name             | Bob Bobbington   |
| 5      | 11               | phone            | 01234 5678910    |
| 6      | 11               | country          | UK               |
| 7      | 12               | name             | Sheila Sausages  |
| 8      | 12               | country          | UK               |
+--------+------------------+------------------+------------------+

+--------------------------+------------------+-----------------+
|      DESIRED RESULT      |                  |                 |
+--------------------------+------------------+-----------------+
| submissions.SubmissionID | EmailAddress     | UserName        |
| 10                       | user@example.com | Paul D'Otherone |
| 11                       | bob@bobs.com     | Bob Bobbington  |
| 12                       | NULL             | Sheila Sausages |
+--------------------------+------------------+-----------------+

另见http://sqlfiddle.com/#!2/78dea/1/0

我尝试了各种内部联接和左联接的组合,但无法获得与上述查询格式相同的结果集。我仍在学习如何使用连接,我发现这很难理解。

没有示例数据,快速尝试一下:

SELECT 
  s.SubmissionID,
  d1.DataContent AS EmailAddress,
  d2.DataContent AS Username
FROM submissions s
JOIN forms AS f1 ON (f1.FormID = s.SubmissionFormID)
JOIN data AS d1 ON (d1.DataFieldName = f1.FormEmailFieldName)
JOIN data AS d2 ON (d2.DataFieldName = f1.FormNameFieldName)
WHERE s.SubmissionFormID = 4

sql fiddle 为:http://sqlfiddle.com/#!2/9f917/1

您可以通过一个连接到 forms 和两个连接到 data 来执行此操作,每个字段一个。

SELECT s.SubmissionID, de.DataContent as EmailAddress,
       dn.DataContent as UserName
FROM submissions s LEFT JOIN
     forms f
     ON f.FormId = s.SubmissionFormID LEFT JOIN
     data dn
     ON d.DataFieldName = f.FormNameFieldName LEFT JOIN
     data de
     ON d.DataFieldName = f.FormEmailFieldName
WHERE s.SubmissionFormID = 4

万一缺少数据,那么你要使用LEFT JOIN。这将确保您获得所有行(您的原始查询所做的)。

我还在查询中添加了 table 个别名。这些使查询更易于编写和阅读。

根据 Olli 和 Gordon 的建议,我得出了以下结果集,该结果集与我的原始查询相同...

SELECT 
  s.SubmissionID,
  d1.DataContent AS EmailAddress,
  d2.DataContent AS Username
FROM submissions s
INNER JOIN forms AS f1 ON (f1.FormID = s.SubmissionFormID)
LEFT JOIN data AS d1 ON (d1.DataFieldName = f1.FormEmailFieldName and d1.DataSubmissionID = s.SubmissionID)
LEFT JOIN data AS d2 ON (d2.DataFieldName = f1.FormNameFieldName and d2.DataSubmissionID = s.SubmissionID)
WHERE s.SubmissionFormID = 4

这看起来是实现我想要的目标的正确方法吗?