2015-07-28 86 views
1

我有兩個表幾乎相同,表示來自服務器的數據和用戶輸入的數據。我想向用戶顯示來自兩者的組合數據的列表,合併任何一個文本列值的重複值。當選擇一行時,我需要能夠訪問子表中的數據,所以需要主鍵和哪個表是鍵。兩個表的聯合創建視圖,合併行

這兩個表在(fk_id,column_a)上都有唯一的約束。

服務器表:

_id | fk_id | column_a 
---------------------- 
1 | 1  | val 1 
2 | 1  | val 2 
3 | 2  | val 3 

用戶輸入表:

_id | uuid | fk_id | column_a 
----------------------------- 
1 | xxxx | 1  | val 1 
2 | xxxx | 1  | val 4 
3 | xxxx | 2  | val 5 

搜索結果我需要那麼將是:

_id | server_id | user_id | fk_id | column_a 
-------------------------------------------- 
1 | 1   | 1  | 1  | val 1 
2 | 2   |   | 1  | val 2 
3 | 3   |   | 2  | val 3 
2 |   | 2  | 1  | val 4 
3 |   | 3  | 2  | val 5 

其實我不關心什麼是結果集的_id列,但我需要_id,因爲我在Android中使用CursorAdaptor。

我希望能做到這一點使用這樣的觀點:

CREATE VIEW all_values AS 
SELECT 
    _id, _id AS server_id, 0 AS user_id, fk_id, column_a 
FROM 
    server_table 
UNION SELECT 
    _id, 0 AS server_id, _id AS user_id, fk_id, column_a 
FROM 
    user_table 
ORDER BY column_a; 

,我可以查詢這樣的:

SELECT * FROM all_values WHERE fk_id = ? 

這是可能使用UNION辦? UNION不會包含重複項,並且UNION ALL將包含所有值。有沒有合併重複的方法,或者我需要做一個基於column_a的值的連接?

+1

是的,但是您必須在兩個SELECT中都具有相同的字段(如果是整數或'AS',則添加'0 AS myMissingField' AS MyMi sFieldField「,如果它是一個字符串,則返回UNION中的任何SELECT,這些SELECT錯誤地忽略了另一個表中的某些字段)。並請刪除不必要的字符串分隔符(**'**) –

+1

因此,使用UNION將合併這兩個結果行?我已經在問題中編輯了CREATE VIEW語句來反映這一點。 – asorenson

+0

是的,正確的。 'UNION'將合併排除最終的重複。 'UNION ALL'也將包含這些。 –

回答

1

UNION會刪除重複項,但只有一個子查詢中包含NULL值的行不會重複。

你必須這樣做,艱難地:

首先,這個查詢獲取並沒有改變所有行:

(SELECT _id, fk_id, column_a FROM server_table 
INTERSECT 
SELECT _id, fk_id, column_a FROM user_table) 

這些行可以直接輸出:

SELECT _id, _id AS server_id, _id AS user_id, fk_id, column_a 
FROM (SELECT _id, fk_id, column_a FROM server_table 
     INTERSECT 
     SELECT _id, fk_id, column_a FROM user_table); 

僅服務器行是服務器表中不在子查詢中的那些行:

SELECT _id, _id AS server_id, NULL AS user_id, fk_id, column_a 
FROM server_table 
WHERE _id NOT IN (SELECT _id FROM (SELECT _id, fk_id, column_a FROM server_table 
            INTERSECT 
            SELECT _id, fk_id, column_a FROM user_table)); 

用戶只行是從用戶表中的行不在子查詢:

SELECT _id, NULL AS server_id, _id AS user_id, fk_id, column_a 
FROM user_table 
WHERE _id NOT IN (SELECT _id FROM (SELECT _id, fk_id, column_a FROM server_table 
            INTERSECT 
            SELECT _id, fk_id, column_a FROM user_table)); 

然後就結合這三個:

SELECT _id, _id AS server_id, _id AS user_id, fk_id, column_a 
FROM (SELECT _id, fk_id, column_a FROM server_table 
     INTERSECT 
     SELECT _id, fk_id, column_a FROM user_table) 
UNION ALL 
SELECT _id, _id, NULL, fk_id, column_a 
FROM server_table 
WHERE _id NOT IN (SELECT _id FROM (SELECT _id, fk_id, column_a FROM server_table 
            INTERSECT 
            SELECT _id, fk_id, column_a FROM user_table)) 
UNION ALL 
SELECT _id + 100000000, NULL, _id, fk_id, column_a 
FROM user_table 
WHERE _id NOT IN (SELECT _id FROM (SELECT _id, fk_id, column_a FROM server_table 
            INTERSECT 
            SELECT _id, fk_id, column_a FROM user_table)); 

(該+ 100000000或類似的東西需要獲得整個結果中唯一的_id值。)

+0

要清楚一點,正如我抽象了一下我的例子,並且我想確保我沒有混淆事物。用戶不會更改數據。他們正在向子表添加全新條目或新條目,在這種情況下,新條目將添加到此user_table(具有server_table中的重複值)。這會在那種情況下工作嗎?從我使用SQL開始到現在已經過去了大約十年,所以我在包圍INTERSECT和UNION時感到有點模糊。 – asorenson

+0

此查詢可檢測到所有差異。我不知道您的服務器表中的副本來自哪裏,但不同之處在於差異,INTERSECT檢測到相同的行。 –