如何创建连接两个表的视图,以显示一个表中的哪些实体未连接到另一表中的实体?

时间:2019-03-06 09:56:21

标签: sql sql-server tsql

我需要创建一个尚未签约的人员和合同的视图。到目前为止,我已经提出了一个嵌套选择集来在我的“订阅”表中收集外键,但是我对如何使用此信息获取某人没有的合同一无所知。

SELECT s.PersonId as pId, s.ContractID as cId
FROM dbo.Subscription AS s
FULL OUTER JOIN dbo.Person as p ON s.PersonId = p.Id
FULL OUTER JOIN dbo.Contract as c ON s.ContractID = c.Id
WHERE p.Id IN (SELECT PersonId FROM dbo.Subscription)

我想做什么的伪代码:

  1. 获取有合同的人
  2. 为每个人获得他们没有的合同
  3. 显示人员和该人员的每个缺失合同

模式(已编辑以删除公司信息):

CREATE TABLE [dbo].[Contract]
(
    [Id] UNIQUEIDENTIFIER NOT NULL PRIMARY KEY, 
    [ContractNumber] NUMERIC(16) NULL
)

CREATE TABLE [dbo].[Person]
(
    [Id] UNIQUEIDENTIFIER NOT NULL PRIMARY KEY,  
    Name nvarchar(200) NOT NULL         
)

CREATE TABLE [dbo].[Subscription]
(
    [Id] UNIQUEIDENTIFIER NOT NULL PRIMARY KEY,
    [PersonID] UNIQUEIDENTIFIER NOT NULL, 
    [ContractID] UNIQUEIDENTIFIER NOT NULL, 
    CONSTRAINT [FK_Subscription_Person] FOREIGN KEY ([PersonID]) REFERENCES [Person]([Id]),
    CONSTRAINT [FK_Subscription_Contract] FOREIGN KEY ([ContractID]) REFERENCES [Contract]([Id])
)

2 个答案:

答案 0 :(得分:2)

这是cross joinnot exists的解决方案:

SELECT p.Id as pId, c.ID as cId
from dbo.Person as p
cross join dbo.Contract as c
WHERE p.Id IN (SELECT PersonId FROM dbo.Subscription as s1)
and not exists(select 1 from dbo.Subscription as s2 where s2.PersonId = p.Id and s2.ContractID = c.Id)
  
      
  1. 获取有合同的人
  2.   

您已经正确使用WHERE p.Id IN (SELECT PersonId FROM dbo.Subscription as s1)

  
      
  1. 为每个人获得他们没有的合同
  2.   

首先,我们使用cross join进行所有组合,然后使用not exists过滤掉不需要的组合

对于(3.),我们只是select我们想要的东西

答案 1 :(得分:0)

使用左联接

SELECT p.*,s.*,c.*
FROM dbo.Person as p
left OUTER JOIN  dbo.Subscription AS s ON s.PersonId = p.Id
left join Contract c on s.ContractID=c.Id