这是我所拥有的非常简化的版本。
我有2个数据库表人员和联系人。 People是原始表,但contacts是一个新表,用于覆盖People表中的数据(这些是真实场景中的不同数据库)
在初始加载时,所有人员记录都会复制到联系人表格,但在初始加载后,新人员可以添加到人员或联系人表格以及设置为已删除的联系人。
我希望所有人都返回,但我希望联系人表格是最重要的,例如
例如
人员表
PersonGuid | PersonId | FirstName | LastName
-----------|----------|-------------|-----
1 xxxx1 | 1 | John | Smith
2 xxxx2 | 2 | Jane | Doe
3 xxxx3 | 3 | John | Doe
4 xxxx4 | 4 | Alice | James
5 xxxx5 | 5 | Claire | Wheeler
通讯录表 (Jane Doe设置为已删除,John Doe不存在,因为在初始导入和添加了Emma Green之后添加了。对于尚未触及的内容,已删除为NULL)
ID | LinkedId | FirstName | LastName | Deleted
-----------|----------|-------------|----------|----------
1 xxxx1 | 1 | John | Smith | NULL
2 xxxx2 | 2 | Jane | Doe | 1
3 xxxx3 | NULL | Emma | Green | 0
4 xxxx4 | 4 | Alice | James | 0
5 xxxx5 | 5 | Claire | Wheeler | NULL
我要返回的内容是:(所有记录,但Jane Doe设置为已删除,因为她在联系人表格中)
ID | LinkedId | FirstName | LastName | Deleted
-----------|----------|-------------|----------|----------
1 xxxx1 | 1 | John | Smith | NULL
2 xxxx2 | 2 | Jane | Doe | 1
3 xxxx3 | 3 | John | Doe | 0
4 xxxx4 | NULL | Emma | Green | 0
5 xxxx5 | 4 | Alice | James | 0
6 xxxx6 | 5 | Claire | Wheeler | NULL
但我得到的是: (Jane Doe Twice)
ID | LinkedId | FirstName | LastName | Deleted
-----------|----------|-------------|----------|----------
1 xxxx1 | 1 | John | Smith | NULL
2 xxxx2 | 2 | Jane | Doe | 1
3 xxxx2 | 2 | Jane | Doe | 0
4 xxxx3 | 3 | John | Doe | 0
5 xxxx4 | NULL | Emma | Green | 0
6 xxxx5 | 4 | Alice | James | 0
7 xxxx6 | 5 | Claire | Wheeler | NULL
我正在尝试联合这两个表,但我不知道如何过滤它以使联系人数据覆盖人员数据,但也从两个表中获取所有数据?
Select PersonGuid as Id,
Personid,
Firstname,
LastName,
cast(0 as bit) as deleted
From DB1.People
Union
Select
Id,
LinkedId as PersonId,
FirstName,
LastName,
Deleted
from DB2.Contacts
我尝试过搜索,但我不确定要搜索什么,所以我的用语可能不对。
编辑 - 真正的查询并不像我的例子那么简单,而且from是每个查询大约6个表的连接。我试图用一个简单的例子说清楚,但不确定这是否使解决方案有所不同?
答案 0 :(得分:0)
尝试使用以下查询。
Select PersonGuid as Id,
Personid,
Firstname,
LastName,
cast(0 as bit) as deleted
From DB1.People
where not exists (select 1 from Contacts WHERE personID=LinkedId and deleted=1)
Union
Select
Id,
LinkedId as PersonId,
FirstName,
LastName,
Deleted
from DB2.Contacts
答案 1 :(得分:0)
看起来你不想要一个联盟 - 而是你想要一个联盟。 FULL OUTER JOIN
返回两个表的所有行,并允许您通过加入ID和LinkedID来识别同一个人的行。
然后,如果存在行,您可以使用ISNULL
函数从“联系人”中进行选择,如果不存在,则可以选择“人员”。
Select ISNULL(C.ID,P.PersonGuid) as Id,
ISNULL(C.LinkedID,Personid) as PersonId,
ISNULL(C.Firstname,P.FirstName) as FirstName,
ISNULL(C.Lastname,P.Lastname) as LastName,
ISNULL(C.Deleted,cast(0 as bit)) as deleted
From DB1.People P
FULL OUTER JOIN DB2.Contacts C on P.PersonID = C.LinkedId
答案 2 :(得分:0)
我认为这可能会做你想要的:
select pc.*
from (select pc.*,
row_number() over (partition by firstname, lastname order by priority) as seqnum
from ((select ID, LinkedId, FirstName, LastName, Deleted, 1 as priority
from contacts
) union all
(select PersonGuid, PersonId, FirstName, LastName, 0 as Deleted, 2
from persons
)
) pc
) pc
where seqnum = 1;
我不确定你是如何在桌子上识别同一个人的。这使用名称,因为这就是你用文字描述问题的方式。
这个想法如下:
UNION ALL
(不是UNION
)合并所有表格中的行。ROW_NUMBER()
根据优先级选择第一个值(PARTITION BY
如果您使用的话会更改,例如,表之间的ID匹配。)答案 3 :(得分:0)
请你试试这个:
SELECT p.PersonGuid,
p.PersonId,
p.FirstName,
p.LastName,
CASE WHEN c.LinkedId IS NULL THEN 0 ELSE c.DELETED END deleted
FROM people p
LEFT JOIN contact c ON c.LinkedId = p.PersonId
UNION
SELECT * FROM #contact a WHERE a.LinkedId IS NULL
答案 4 :(得分:-1)
UNION
会为您提供没有重复的记录,因此要使用联系人覆盖人员数据,请更改查询的顺序:
Select Id, LinkedId as PersonId, FirstName, LastName, Deleted
from DB2.Contacts
UNION
Select PersonGuid as Id,Personid,Firstname,LastName,cast(0 as bit) as deleted
From DB1.People
要获取所有记录,请使用UNION ALL
代替UNION
。这也将返回重复项。