2016-09-06 17 views
3

這是我所擁有的一個非常簡化的版本。SQL Union但過濾出部分重複文件

我有2個數據庫表人員和聯繫人。 人是原始表,但聯繫人是用於覆蓋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的設置爲刪除,李四不存在由於作爲當時INTIAL導入後添加和艾瑪·格林已被添加。刪除爲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 

我想返回是: (所有的記錄,但與李四設爲刪除,因爲她是在聯繫人表)

 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的兩次)

 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

是李四和李四意味着有相同的ID或者是一個錯字? Emma Green和John Doe也有同樣的問題嗎? –

+0

剛注意到這一點。不,他們不打算擁有相同的ID。我現在要編輯 – Bex

回答

0

看起來你不想要一個聯盟 - 而是你想加入。 FULL OUTER JOIN返回兩個表的所有行,並允許您通過加入您的ID和LinkedID來識別同一個人的行。

然後,您可以使用ISNULL函數從聯繫人中選擇行(如果存在行)或選擇Person(如果不存在)。

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 
+0

我可能過多地簡化了我的示例。真正的查詢來自大約6個表的連接。你會說,而不是將我的每個查詢插入臨時表並加入他們? – Bex

+1

或者將你的連接替換爲FROM(FROM這裏的大連接)P FULL OUTER JOIN(這裏的連接的大連接)C ON .....'或者構建連接表的視圖並引用它。 – BeanFrog

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 
+0

在「真實」查詢中,From實際上加入了大約6個表格,所以還有另一種方法來做這件事,因爲我認爲在查詢中添加一個不存在的東西似乎是不合理的。 – Bex

-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。這將返回重複。

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()根據優先級來選擇第一個值(如果您使用id表示匹配,那麼PARTITION BY會發生變化)。
  • 最後,選擇行,其中的行數爲1
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