将子查询转换为连接

时间:2015-01-30 10:44:30

标签: mysql sql join subquery

给出以下架构......

Schema 我将如何转换以下查询以使用连接(与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

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

3 个答案:

答案 0 :(得分:1)

没有样本数据,只需快速尝试:

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 for it:http://sqlfiddle.com/#!2/9f917/1

答案 1 :(得分: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。这将确保您获得所有行(您的原始查询所执行的行)。

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

答案 2 :(得分:0)

从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

这似乎是实现我想要的正确方法吗?