加入两个表并显示一个表中的数据

时间:2014-09-25 12:39:05

标签: sql join

我需要加入这两个表

         fields_data                                       fields
+------------+-----------+------+             +------+-------------+----------+
| relationid | fieldname | data |             | name | displayname | position |
+------------+-----------+------+             +------+-------------+----------+
|     2      |    ftp    | test |             | user |  Username   |   top    |
|     2      |   other   | 1234 |             | pass |  Password   |   top    |
+------------+-----------+------+             | ftp  |    FTP      |   top    |
                                              | log  |    Log      |   top    |
                                              | txt  |    Text     |   mid    |
                                              +------+-------------+----------+

我想获取“fields”表中的所有行,如果它们的位置为“top”,并且如果一行在name = fieldname上匹配来自fields_data,它还应该显示数据。这是我的加入

SELECT 
fd.`data`,
fd.`relationid`, 
fd.`fieldname`, 
f.`name`, 
f.`displayname` 

FROM `fields` AS f

LEFT OUTER JOIN `fields_data` AS fd 
ON fd.`fieldname` = f.`name` 

WHERE f.`position`='top' AND (fd.`relationid`='3' OR fd.`relationid` IS NULL)

我的问题是上面的查询只给出了这个结果:

+------+------------+-----------+------+-------------+
| data | relationid | fieldname | name | displayname |
+------+------------+-----------+------+-------------+
| NULL | NULL       | NULL      | user |  Username   |  
| NULL | NULL       | NULL      | pass |  Password   |  
| NULL | NULL       | NULL      | log  |    Log      |  
+------+------------+-----------+------+-------------+

由于它与“2”的关系,所以缺少名为“ftp”的字段。但是我仍然希望将其显示为结果,但是像其他字符一样显示它。如果SQL查询具有“fd。relationid ='2'”而不是3,它将给出相同的结果,但是在名称中包含ftp的行,将数据保存在三个字段中。

我希望你明白我的意思..我的英语不是最好的..继续我想要的结果:

   with above query containing fd.`relationid`='3'
+------+------------+-----------+------+-------------+
| data | relationid | fieldname | name | displayname |
+------+------------+-----------+------+-------------+
| NULL | NULL       | NULL      | user |  Username   |  
| NULL | NULL       | NULL      | pass |  Password   |  
| NULL | NULL       | NULL      | ftp  |    FTP      | 
| NULL | NULL       | NULL      | log  |    Log      |  
+------+------------+-----------+------+-------------+

   with above query containing fd.`relationid`='2'
+------+------------+-----------+------+-------------+
| data | relationid | fieldname | name | displayname |
+------+------------+-----------+------+-------------+
| NULL | NULL       | NULL      | user |  Username   |  
| NULL | NULL       | NULL      | pass |  Password   |  
| test | 2          | ftp       | ftp  |    FTP      | 
| NULL | NULL       | NULL      | log  |    Log      |  
+------+------------+-----------+------+-------------+

1 个答案:

答案 0 :(得分:0)

您希望将条件移至on子句:

SELECT fd.`data`, fd.`relationid`, fd.`fieldname`, f.`name`, f.`displayname` 
FROM `fields` f LEFT OUTER JOIN
     `fields_data` fd 
      ON fd.`fieldname` = f.`name` AND fd.`relationid` = '3'
WHERE f.`position`='top' ;

有趣的是,您的查询和此查询的语义不同 - 您找到了确切的情况:当另一个值匹配时,where子句形式过滤掉行。这仍将保留一切。

作为注释,以下内容也可以满足您的需求:

SELECT fd.`data`, fd.`relationid`, fd.`fieldname`, f.`name`, f.`displayname` 
FROM `fields` f LEFT OUTER JOIN
     (SELECT fd.*
      FROM `fields_data` fd 
      WHERE  fd.`relationid` = '3'
     ) fd
     ON fd.`fieldname` = f.`name`
WHERE f.`position` = 'top' ;

我不建议以这种方式编写查询,特别是在MySQL中(因为子查询已实现)。但是,理解为什么你的版本与这些版本不同(以及为什么它们是相同的)是掌握外连接的一大进步。