我有两个几乎完全相同的表,表示来自服务器的数据和用户输入的数据。我想向用户显示两个组合数据的列表,合并一个文本列的值的任何重复项。当选择一行时,我需要能够访问子表中的数据,因此需要主键和键来自哪个表。
两个表都对(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的值进行连接?
答案 0 :(得分: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
值。)