SQL 外部联接 -- 联接需要 3 个表

SQL Outer Join -- Join requires 3 tables

我正在使用 SQL 服务器查询设计器来尝试形成一个外部查询,该查询将 return 每个有家庭保单和没有保单的被保险人的全名和地址。我的创建语句如下:

    CREATE TABLE Address (
    AddressID integer NOT NULL,
    HouseNumber Integer NOT NULL,
    Street varchar(20) NOT NULL,
    CityCounty varchar(20) NOT NULL,
    StateAbb char(2),
    CountryAbb char(2) NOT NULL,
    Zip char(5) NOT NULL,
    LastUpdatedBy varchar(20) NOT NULL,
    LastUpdated date NOT NULL,
    CONSTRAINT PK_Address PRIMARY KEY (AddressID));

    CREATE TABLE Insured(
    InsuredID integer NOT NULL,
    FirstName varchar(15) NOT NULL,
    LastName varchar(15) NOT NULL,
    MI char(1),
    DateOfBirth date NOT NULL,
    CreditScore integer NOT NULL,
    AddressID integer NOT NULL,
    DriversLicenseNumber varchar(35), 
    LastUpdatedBy varchar(20) NOT NULL,
    LastUpdated date NOT NULL,
    CONSTRAINT PK_Insured PRIMARY KEY (InsuredID),
    CONSTRAINT FK_InsuredAddress FOREIGN KEY (AddressID) references  Address);

    CREATE TABLE Policy(
    PolicyID integer NOT NULL,
    EffectiveDate date NOT NULL,
    TerminationDate date NOT NULL,
    Amount Numeric (8,2) NOT NULL,
    PolicyYear integer NOT NULL,
    PolicyType char(1) NOT NULL,
    InsuredID integer NOT NULL,
    AddressID integer NOT NULL,
    LastUpdatedBy varchar(20) NOT NULL,
    LastUpdated date NOT NULL,
    CONSTRAINT PK_Policy PRIMARY KEY (PolicyID),
    CONSTRAINT FK_PolicyAddress FOREIGN KEY (AddressID) references Address,
    CONSTRAINT FK_PolicyInsured FOREIGN KEY (InsuredID) references Insured);

    CREATE TABLE Home(
    PolicyID integer NOT NULL,
    ExteriorType varchar(30) NOT NULL,
    Alarm char(3) NOT NULL,
    DistanceToFireStation integer NOT NULL,
    LastUpdatedBy varchar(20) NOT NULL,
    LastUpdated date NOT NULL,
    CONSTRAINT PK_Home PRIMARY KEY (PolicyID),
    CONSTRAINT FK_HomePolicy FOREIGN KEY (PolicyID) references Policy);

    CREATE TABLE Auto(
    PolicyID integer NOT NULL,
    VinNumber varchar(30) NOT NULL,
    Make varchar(15) NOT NULL,
    Model varchar(20) NOT NULL,
    MilesPerYear integer NOT NULL,
    LastUpdatedBy varchar(20) NOT NULL,
    LastUpdated date NOT NULL,
    CONSTRAINT PK_Auto PRIMARY KEY (PolicyID),
    CONSTRAINT FK_AutoPolicy FOREIGN KEY (PolicyID) references Policy);

我认为查询需要表地址、保险、政策和外部右或左连接,但我无法让 SQL 服务器识别它,因为它不断形成内部连接和交叉连接。对于 return 有家庭保单的被保险人及其地址和没有保单的被保险人及其地址的查询,我需要什么?

到目前为止我尝试过的:

SELECT Insured.InsuredID, Insured.FirstName, 
       Insured.LastName, Address.HouseNumber, 
       Policy.PolicyID 
FROM Address RIGHT JOIN Policy 
ON Address.AddressID = Policy.AddressID 
RIGHT JOIN Insured ON Policy.AddressID = Insured.AddressID 
ORDER BY Insured.InsuredID

这是最近的查询,return对于有家庭保险的被保险人,我需要什么,但对于没有保险的被保险人,我在地址中得到空值。

SELECT i.InsuredID, i.FirstName, i.MI, i.LastName,            
a.HouseNumber, a.Street, a.CityCounty, a.StateAbb, a.CountryAbb, a.Zip 
FROM INSURED i 
LEFT JOIN (SELECT * FROM Policy WHERE PolicyType = 'H') HomePolicy on    
i.InsuredID = HomePolicy.InsuredID 
LEFT JOIN Address a on HomePolicy.AddressID = a.AddressID;

你能试试这个查询吗:

SELECT i.InsuredID,
i.FirstName,
i.LastName,
a.HouseNumber,
p.PolicyID
FROM insured i
LEFT JOIN policy p ON i.AddressID = p.AddressID AND p.PolicyType = 'H'
LEFT JOIN address a ON i.AddressID = a.AddressID
ORDER BY i.InsuredID;

我认为连接顺序错误。这会给你你需要的吗? 更新:将被保险人 table 加入地址 table 将向您显示地址,无论他们是否有保单。

数据库设计似乎 good.I 认为我们对 "PolicyType" 列有一些小疑问。它具有什么价值以及此专栏的目的是什么。

PolicyType='H'表示是国内政策。或者查找相同查询的其他方法是检查 policyid 是否存在于 home table.

这是正确的吗?

主查询,

What do I need for a query that returns insureds with home policies and their addresses and insureds with no policy and their addresses?

检查这个脚本,

--insureds with home policies and their addresses 
select i.InsuredID,
i.FirstName,
i.LastName
A.HouseNumber
,1 INDICATE
from Insured i
INNER JOIN policy p ON i.InsuredID = p.InsuredID 
INNER JOIN [Address] A ON A.ADDRESSID=I.ADDRESSID
WHERE  EXISTS(SELECT PolicyID FROM Home H WHERE h.PolicyID=P.PolicyID)
AND NOT EXISTS(SELECT PolicyID FROM [Auto] a WHERE A.PolicyID=P.PolicyID)

UNION ALL
--insureds with no policy and their addresses
select i.InsuredID,
i.FirstName,
i.LastName
,A.HouseNumber
,0 INDICATE
from Insured i
INNER JOIN [Address] A ON A.ADDRESSID=I.ADDRESSID
WHERE  EXISTS(SELECT InsuredID FROM   policy p WHERE i.InsuredID = p.InsuredID )

我使用了 "EXISTS clause",因为您的输出中不需要 table 列。