2015-07-28 110 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检测到相同的行。 –