将子查询转换为连接
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
这看起来是实现我想要的目标的正确方法吗?
给定以下架构...
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
这看起来是实现我想要的目标的正确方法吗?