加入3个表并过滤SQL

时间:2012-03-18 03:10:59

标签: sql join filter

我使用的是AdvetureWorks数据库。这是我想做的事情: 给我姓氏,名字,公司名称,并列出客户Virginia Miller的所有地址,包括地址类型,地址,城市和州。 您需要将3个表连接在一起并过滤结果。你应该只获得2行。 这就是我到目前为止......

Select
SalesLT.Customer.LastName,
SalesLT.Customer.FirstName,
SalesLT.Customer.CompanyName,
CustomerAddress.AddressType,
SalesLT.Address.AddressLine1,
SalesLT.Address.City,
SalesLT.Address.StateProvince

From SalesLT.Customer C, SalesLT.CustomerAddress CA, SalesLT.Address A


 join SalesLT.CustomerAddress

on SalesLT.Address.AddressID=SalesLT.CustomerAddress.AddressID


join SalesLT.Customer
on SalesLT.CustomerAddress.CustomerID=SalesLT.Customer.CustomerID

join SalesLT.Address
on SalesLT.CustomerAddress.AddressID=SalesLT.Address.AddressID

Where SalesLT.Customer.FirstName = 'Virginia'

是的我是新人,不太了解加入。非常感谢任何正确方向的推动!

3 个答案:

答案 0 :(得分:1)

我相信以下内容应该可以解决您的问题。

USE SalesLT

SELECT
    c.LastName,
    c.FirstName,
    c.CompanyName,
    ca.AddressType,
    a.AddressLine1,
    a.City,
    a.StateProvince

FROM
    Customer c

JOIN 
    CustomerAddress ca
    ON c.CustomerID=ca.CustomerID

JOIN 
    Address a
    ON ca.AddressID=a.AddressID

WHERE 
    c.FirstName = 'Virginia'
    AND c.LastName = 'Miller'

构建SQL查询时,我发现最好只从主表中选择我想要的数据。因此,在此查询的情况下,您正在查找有关特定客户的信息(在此示例中,您已经为其提供了Virginia Miller)。因此,只需获取有关该客户的信息,查询就会像这样。

USE SalesLT

SELECT
    c.LastName,
    c.FirstName

FROM
    Customer c

WHERE
    c.FirstName = 'Virginia' 
    AND c.LastName = 'Miller'

所以你在那里完成的工作是通过指示你将使用哪个数据库(即USE SalesLT系列)开始的。这将有助于输入,因此您不必在每个表名之前添加它。

接下来,您将选择您感兴趣的列名(LastName和FirstName)。他们有“c”。在他们面前指定表的昵称或“别名”,我们说SQL可以在中找到该数据。

在“FROM”行中,您可以看到您正在告诉SQL查看Customer表,并且您将为该表提供别名“c”,以便您可以快速引用它并使其清楚哪些列属于查询中的哪些表。

现在您正在为弗吉尼亚米勒获取数据,让我们看看下一篇文章。您需要弗吉尼亚州的地址,因此您需要某种方式将地址数据与客户数据相关联。

幸运的是,AdventureWorks数据库很容易实现,因为它们具有CustomerAddress“join”表。像这样的表被设计为在具有某种类型的ID列的两个表之间简单地链接记录。在这种情况下,它链接CustomerID(Customer表中的一列)和AddressID(Address表中的一列),以便我们可以找出特定客户可能拥有的地址。

所以现在我们知道我们需要来自CustomerAddress的数据,所以我们应该将下一部分添加到我们的查询中。

USE SalesLT

SELECT
    c.LastName,
    c.FirstName,
    c.CompanyName,
    ca.AddressType

FROM
    Customer c

JOIN 
    CustomerAddress ca
    ON c.CustomerID=ca.CustomerID  

WHERE
        c.FirstName = 'Virginia' 
        AND c.LastName = 'Miller'

上面代码中的新部分是添加从CustomerAddress表中选择AddressType,然后告诉SQL Customer表和CustomerAddress表是如何相关的。它可以在它们之间连接记录,因为Customer表中的CustomerID等于CustomerAddress表中的Customer ID(JOIN CustomerAddress ca ON c.CustomerID = ca.CustomerID)。 “ca”是我们为CustomerAddress表提供的昵称或别名,因此我们使用它来在查询中的其他位置引用它。

现在我们已经让查询的那部分工作了,我们已准备好在最后阶段获取实际的地址信息。

USE SalesLT

SELECT
    c.LastName,
    c.FirstName,
    c.CompanyName,
    ca.AddressType

FROM
    Customer c

JOIN 
    CustomerAddress ca
    ON c.CustomerID = ca.CustomerID  

JOIN
    Address a
    ON a.AddressID = ca.AddressID

WHERE
        c.FirstName = 'Virginia' 
        AND c.LastName = 'Miller'

最后一步只是添加了有关Address表如何与CustomerAddress表相关的附加信息。基本上,CustomerAddress中的AddressID列等于Address中的AddressID列。

现在我们回到原始查询中,包含我们想要的所有信息,表SQL可以找到数据,以及我们在表之间定义的关系。

逐步解决问题通常是一个很好的方法。

答案 1 :(得分:1)

select语句的目的是以特定方式返回一些数据。这大致采用以下形式:

select <columns>
from <table/group of tables joined together/sub-query/tvf etc.>
where <condition>

1 - 现在,你遇到问题的那一点似乎是中间位 - 我们会先这样做。

您有三个表格,其中包含您想要的数据:

SalesLT.Customer 
SalesLT.CustomerAddress 
SalesLT.Address

并且您希望将它们一起连接到数据彼此相关的列,在本例中为CustomerID。内部连接语句采用以下形式(选择内连接,因为所有条目在其他表中都匹配!):

table1 inner join table2 on table1.columnname = table2.columnname

如果我们将您的示例与此语法匹配,我们就会得到:

SalesLT.CustomerAddress INNER JOIN
                      SalesLT.Customer ON SalesLT.CustomerAddress.CustomerID = SalesLT.Customer.CustomerID INNER JOIN
                      SalesLT.Address ON SalesLT.CustomerAddress.AddressID = SalesLT.Address.AddressID

现在,select语句的其余部分将此查询视为数据的一个大“集合”,几乎就像它是一个表一样 - 每个列都由表名预先固定。如果您在语句的其他地方引用其中一个,则并不总是需要包含完全限定的名称(因为只要结果集中的名称不超过一列,就可以猜测。)

2 - 您似乎已经掌握了过滤where子句,但您似乎只是在使用名字进行过滤,尽管您有初步要求。添加一个很容易:

WHERE     (SalesLT.Customer.FirstName = 'Virginia') AND (SalesLT.Customer.LastName = N'Miller')

3 - 最后还有一个小问题你想要回来 - 你已经有了正确的答案。

结合我们一起完成的工作,您会得到以下查询:

SELECT     SalesLT.Customer.LastName, SalesLT.Customer.FirstName, SalesLT.Customer.CompanyName, SalesLT.CustomerAddress.AddressType, 
                      SalesLT.Address.AddressLine1, SalesLT.Address.City, SalesLT.Address.StateProvince
FROM         SalesLT.CustomerAddress INNER JOIN
                      SalesLT.Customer ON SalesLT.CustomerAddress.CustomerID = SalesLT.Customer.CustomerID INNER JOIN
                      SalesLT.Address ON SalesLT.CustomerAddress.AddressID = SalesLT.Address.AddressID
WHERE     (SalesLT.Customer.FirstName = 'Virginia') AND (SalesLT.Customer.LastName = N'Miller')

答案 2 :(得分:0)

我没有安装Adventure DB,所以我不知道这些关系。假设您提到的关系有效,这应该有效:

USE SalesLT

SELECT
c.LastName,
c.FirstName,
c.CompanyName,
ca.AddressType,
a.AddressLine1,
a.City,
a.StateProvince,
FROM Customer C
INNER JOIN CustomerAddress ca ON ca.CustomerID = c.CustomerID
LEFT JOIN Address a ON a.AddressID = ca.AddressID
WHERE c.FirstName = 'Virginia'

备注 - 我在地址上使用了LEFT JOIN,因为我不知道是否有可能没有地址记录的客户记录。在可能的情况下,即使没有地址,您仍希望为客户提供记录,请使用LEFT JOIN和COALESCE来识别NULL记录。