如何在SQL查询中获取联接

时间:2016-04-11 16:55:03

标签: sql ms-access

我有两张表,如下:

First_Name Last_Name
  Bill       Smith
  David      Williams
  Fred       Jones
  Freda      Jones
  Jane       Smith
  John       Smith
  Peter      Williams
  Sally      Williams

宠物

Species Title  Owner
  Dog    Fido   Jones
  Cat    Tibs   Jones
  Dog    Jock   Williams

我知道这是一个奇怪的数据库设计,但请不要告诉我重新设计数据库。这是一个代表真实问题的例子,它更复杂,无法重新设计。

我正在尝试制定一个查询,它将为每个人返回一行,以及一个包含其Cat标题的列,如果他们没有猫,则为null(我使用Title因为{{1}是一个保留字和Access抱怨)。

我最接近的是:

Name

然而,这并未列出威廉姆斯家族的任何行,因为他们拥有一只狗。

我已经将其标记为MS Access,因为我实际上使用的是Access 97(请不要问!),但是,除了Access相当有限的Join设施之外,它应该是一般的SQL问题。

4 个答案:

答案 0 :(得分:5)

编辑:Access中的左连接语法会导致故障,这意味着对于访问,我们需要涉及子查询。这看起来像(未经测试的);

SELECT People.*, Pets.Title
FROM People LEFT JOIN 
  [SELECT Pets.* FROM Pets WHERE Pets.Species = 'Cat']. AS Pets 
    ON People.Last_Name = Pets.Owner

- 原始答案 -

你似乎想要的是一个常规的左连接,另外一个条件是宠物需要成为一只猫;

SELECT People.*, Pets.Title
FROM People LEFT JOIN Pets 
  ON People.Last_Name = Pets.Owner AND Pets.Species = 'Cat'

将cat条件放在WHERE子句中的原因是where子句消除了所有非匹配,而将它放在ON子句中会产生结果如果无法找到匹配项,则为NULL(正如您描述的所需结果)

答案 1 :(得分:1)

  

这并未列出威廉姆斯家族的任何行,因为他们拥有一只狗

那是因为WHERE条款:

WHERE Pets.Species IS NULL OR Pets.Species = "Cat"

如果Pets.Species"Dog",那么这将评估为false,因此不会显示这些记录。首先完全删除该条款:

SELECT People.*, Pets.Title
FROM People
LEFT JOIN Pets ON People.Last_Name = Pets.Owner

现在您正在获取所需的记录,但不是您想要的数据Title列显示任意值,您只希望它显示"Cat"NULL。您可以调整JOIN来实现:

SELECT People.*, Pets.Title
FROM People
LEFT JOIN Pets ON People.Last_Name = Pets.Owner
              AND Pets.Species = 'Cat'

这将过滤已加入的表,但不会过滤整个结果集。

答案 2 :(得分:0)

试试这个

SELECT People.*, case when Pets.Species = 'Cat' then Pets.Title else null end as Title
 FROM People LEFT JOIN Pets ON People.Last_Name = Pets.Owner

答案 3 :(得分:0)

对于后人 - 我终于得到了它:

SELECT People.*, Pets.Title FROM 
People LEFT JOIN (SELECT * FROM Pets WHERE Species='Cat') AS PeopleWithCats 
ON People.Last_Name=PeopleWithCats.Owner